使用C++設(shè)計開發(fā)一個功能完善的多進程管理器
引言
在實際的軟件開發(fā)中,我們經(jīng)常需要管理多個相互協(xié)作的進程。一個健壯的多進程管理器不僅需要能夠按照依賴順序啟動進程,還要能夠優(yōu)雅地停止進程,并在進程意外崩潰時自動重啟。本文將詳細介紹如何使用C++開發(fā)一個功能完善的多進程管理器。
核心功能需求
一個完整的多進程管理器應(yīng)該具備以下核心功能:
- 進程順序啟動: 根據(jù)進程間的依賴關(guān)系,按照正確的順序啟動各個進程
- 進程停止管理: 能夠優(yōu)雅地停止進程,并處理停止失敗的情況
- 崩潰自動重啟: 監(jiān)控進程狀態(tài),在進程異常退出時自動重啟
系統(tǒng)架構(gòu)設(shè)計
進程配置結(jié)構(gòu)
首先,我們需要定義進程的配置信息:
#include <string>
#include <vector>
#include <memory>
struct ProcessConfig {
std::string name; // 進程名稱
std::string executable; // 可執(zhí)行文件路徑
std::vector<std::string> args; // 啟動參數(shù)
int startDelay; // 啟動延遲(毫秒)
int maxRestarts; // 最大重啟次數(shù)
bool autoRestart; // 是否自動重啟
std::vector<std::string> dependencies; // 依賴的進程
};
進程狀態(tài)管理
定義進程的運行狀態(tài):
enum class ProcessState {
STOPPED, // 已停止
STARTING, // 啟動中
RUNNING, // 運行中
STOPPING, // 停止中
CRASHED // 已崩潰
};
struct ProcessInfo {
ProcessConfig config;
pid_t pid;
ProcessState state;
int restartCount;
std::chrono::system_clock::time_point lastStartTime;
std::chrono::system_clock::time_point lastCrashTime;
};
進程管理器實現(xiàn)
類定義
#include <map>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
class ProcessManager {
public:
ProcessManager();
~ProcessManager();
// 添加進程配置
bool addProcess(const ProcessConfig& config);
// 啟動所有進程
bool startAll();
// 啟動指定進程
bool startProcess(const std::string& name);
// 停止所有進程
void stopAll();
// 停止指定進程
bool stopProcess(const std::string& name);
// 獲取進程狀態(tài)
ProcessState getProcessState(const std::string& name) const;
// 啟動監(jiān)控線程
void startMonitoring();
private:
// 按依賴順序排序進程
std::vector<std::string> getStartOrder();
// 實際啟動進程
pid_t launchProcess(ProcessInfo& info);
// 監(jiān)控進程狀態(tài)
void monitorProcesses();
// 重啟崩潰的進程
void restartProcess(const std::string& name);
// 檢查進程是否存活
bool isProcessAlive(pid_t pid);
std::map<std::string, ProcessInfo> processes_;
std::mutex mutex_;
std::atomic<bool> running_;
std::thread monitorThread_;
};
構(gòu)造與析構(gòu)
ProcessManager::ProcessManager() : running_(false) {
}
ProcessManager::~ProcessManager() {
stopAll();
if (monitorThread_.joinable()) {
running_ = false;
monitorThread_.join();
}
}
添加進程配置
bool ProcessManager::addProcess(const ProcessConfig& config) {
std::lock_guard<std::mutex> lock(mutex_);
if (processes_.find(config.name) != processes_.end()) {
std::cerr << "Process " << config.name << " already exists" << std::endl;
return false;
}
ProcessInfo info;
info.config = config;
info.pid = -1;
info.state = ProcessState::STOPPED;
info.restartCount = 0;
processes_[config.name] = info;
return true;
}
依賴關(guān)系排序
使用拓撲排序算法確定進程啟動順序:
std::vector<std::string> ProcessManager::getStartOrder() {
std::vector<std::string> order;
std::map<std::string, int> inDegree;
std::map<std::string, std::vector<std::string>> graph;
// 初始化入度
for (const auto& pair : processes_) {
inDegree[pair.first] = 0;
}
// 構(gòu)建依賴圖
for (const auto& pair : processes_) {
const std::string& name = pair.first;
const auto& deps = pair.second.config.dependencies;
for (const auto& dep : deps) {
graph[dep].push_back(name);
inDegree[name]++;
}
}
// 拓撲排序
std::vector<std::string> queue;
for (const auto& pair : inDegree) {
if (pair.second == 0) {
queue.push_back(pair.first);
}
}
while (!queue.empty()) {
std::string current = queue.back();
queue.pop_back();
order.push_back(current);
for (const auto& next : graph[current]) {
inDegree[next]--;
if (inDegree[next] == 0) {
queue.push_back(next);
}
}
}
// 檢查是否有循環(huán)依賴
if (order.size() != processes_.size()) {
std::cerr << "Circular dependency detected!" << std::endl;
order.clear();
}
return order;
}
啟動進程
pid_t ProcessManager::launchProcess(ProcessInfo& info) {
pid_t pid = fork();
if (pid < 0) {
std::cerr << "Failed to fork process: " << info.config.name << std::endl;
return -1;
}
if (pid == 0) {
// 子進程
std::vector<char*> argv;
argv.push_back(const_cast<char*>(info.config.executable.c_str()));
for (auto& arg : info.config.args) {
argv.push_back(const_cast<char*>(arg.c_str()));
}
argv.push_back(nullptr);
execv(info.config.executable.c_str(), argv.data());
// 如果execv返回,說明執(zhí)行失敗
std::cerr << "Failed to execute: " << info.config.executable << std::endl;
exit(1);
}
// 父進程
return pid;
}
bool ProcessManager::startProcess(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
std::cerr << "Process not found: " << name << std::endl;
return false;
}
ProcessInfo& info = it->second;
if (info.state == ProcessState::RUNNING) {
std::cout << "Process already running: " << name << std::endl;
return true;
}
// 檢查依賴進程是否已啟動
for (const auto& dep : info.config.dependencies) {
auto depIt = processes_.find(dep);
if (depIt == processes_.end() ||
depIt->second.state != ProcessState::RUNNING) {
std::cerr << "Dependency not running: " << dep << std::endl;
return false;
}
}
info.state = ProcessState::STARTING;
// 啟動延遲
if (info.config.startDelay > 0) {
std::this_thread::sleep_for(
std::chrono::milliseconds(info.config.startDelay));
}
pid_t pid = launchProcess(info);
if (pid < 0) {
info.state = ProcessState::STOPPED;
return false;
}
info.pid = pid;
info.state = ProcessState::RUNNING;
info.lastStartTime = std::chrono::system_clock::now();
std::cout << "Started process: " << name << " (PID: " << pid << ")" << std::endl;
return true;
}
bool ProcessManager::startAll() {
std::vector<std::string> order = getStartOrder();
if (order.empty()) {
return false;
}
for (const auto& name : order) {
if (!startProcess(name)) {
std::cerr << "Failed to start process: " << name << std::endl;
return false;
}
}
return true;
}
停止進程
bool ProcessManager::stopProcess(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
return false;
}
ProcessInfo& info = it->second;
if (info.state != ProcessState::RUNNING) {
return true;
}
info.state = ProcessState::STOPPING;
// 發(fā)送SIGTERM信號
if (kill(info.pid, SIGTERM) == 0) {
// 等待進程優(yōu)雅退出
int status;
pid_t result = waitpid(info.pid, &status, WNOHANG);
if (result == 0) {
// 進程還在運行,等待一段時間
std::this_thread::sleep_for(std::chrono::seconds(5));
// 再次檢查
result = waitpid(info.pid, &status, WNOHANG);
if (result == 0) {
// 強制終止
std::cout << "Force killing process: " << name << std::endl;
kill(info.pid, SIGKILL);
waitpid(info.pid, &status, 0);
}
}
}
info.pid = -1;
info.state = ProcessState::STOPPED;
std::cout << "Stopped process: " << name << std::endl;
return true;
}
void ProcessManager::stopAll() {
// 按照啟動順序的反序停止進程
std::vector<std::string> order = getStartOrder();
std::reverse(order.begin(), order.end());
for (const auto& name : order) {
stopProcess(name);
}
}
進程監(jiān)控與自動重啟
bool ProcessManager::isProcessAlive(pid_t pid) {
if (pid <= 0) {
return false;
}
int status;
pid_t result = waitpid(pid, &status, WNOHANG);
if (result == 0) {
// 進程仍在運行
return true;
} else if (result == pid) {
// 進程已退出
return false;
} else {
// 錯誤
return false;
}
}
void ProcessManager::restartProcess(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
return;
}
ProcessInfo& info = it->second;
// 檢查重啟次數(shù)限制
if (info.restartCount >= info.config.maxRestarts) {
std::cerr << "Max restart count reached for: " << name << std::endl;
info.state = ProcessState::STOPPED;
return;
}
info.restartCount++;
info.lastCrashTime = std::chrono::system_clock::now();
std::cout << "Restarting process: " << name
<< " (attempt " << info.restartCount << ")" << std::endl;
// 等待一小段時間再重啟,避免快速重啟循環(huán)
std::this_thread::sleep_for(std::chrono::seconds(1));
info.state = ProcessState::STARTING;
pid_t pid = launchProcess(info);
if (pid > 0) {
info.pid = pid;
info.state = ProcessState::RUNNING;
info.lastStartTime = std::chrono::system_clock::now();
std::cout << "Restarted process: " << name << " (PID: " << pid << ")" << std::endl;
} else {
info.state = ProcessState::CRASHED;
std::cerr << "Failed to restart process: " << name << std::endl;
}
}
void ProcessManager::monitorProcesses() {
while (running_) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : processes_) {
ProcessInfo& info = pair.second;
if (info.state == ProcessState::RUNNING) {
if (!isProcessAlive(info.pid)) {
std::cerr << "Process crashed: " << pair.first << std::endl;
info.state = ProcessState::CRASHED;
if (info.config.autoRestart) {
// 解鎖后重啟,避免死鎖
std::string name = pair.first;
mutex_.unlock();
restartProcess(name);
mutex_.lock();
}
}
}
}
}
}
void ProcessManager::startMonitoring() {
running_ = true;
monitorThread_ = std::thread(&ProcessManager::monitorProcesses, this);
}
ProcessState ProcessManager::getProcessState(const std::string& name) const {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
return ProcessState::STOPPED;
}
return it->second.state;
}
使用示例
基本使用
#include "ProcessManager.h"
int main() {
ProcessManager manager;
// 配置數(shù)據(jù)庫進程
ProcessConfig dbConfig;
dbConfig.name = "database";
dbConfig.executable = "/usr/bin/postgres";
dbConfig.args = {"-D", "/var/lib/postgresql/data"};
dbConfig.startDelay = 0;
dbConfig.maxRestarts = 3;
dbConfig.autoRestart = true;
// 配置應(yīng)用服務(wù)進程(依賴數(shù)據(jù)庫)
ProcessConfig appConfig;
appConfig.name = "app_server";
appConfig.executable = "/opt/myapp/server";
appConfig.args = {"--port", "8080"};
appConfig.startDelay = 2000; // 等待數(shù)據(jù)庫啟動
appConfig.maxRestarts = 5;
appConfig.autoRestart = true;
appConfig.dependencies = {"database"};
// 配置Web服務(wù)進程(依賴應(yīng)用服務(wù))
ProcessConfig webConfig;
webConfig.name = "web_server";
webConfig.executable = "/usr/sbin/nginx";
webConfig.args = {"-c", "/etc/nginx/nginx.conf"};
webConfig.startDelay = 1000;
webConfig.maxRestarts = 3;
webConfig.autoRestart = true;
webConfig.dependencies = {"app_server"};
// 添加進程配置
manager.addProcess(dbConfig);
manager.addProcess(appConfig);
manager.addProcess(webConfig);
// 啟動所有進程
if (manager.startAll()) {
std::cout << "All processes started successfully" << std::endl;
} else {
std::cerr << "Failed to start some processes" << std::endl;
return 1;
}
// 啟動監(jiān)控線程
manager.startMonitoring();
// 等待用戶輸入停止信號
std::cout << "Press Enter to stop all processes..." << std::endl;
std::cin.get();
// 停止所有進程
manager.stopAll();
return 0;
}
高級用法:信號處理
#include <csignal>
ProcessManager* g_manager = nullptr;
void signalHandler(int signal) {
if (signal == SIGINT || signal == SIGTERM) {
std::cout << "\nReceived shutdown signal..." << std::endl;
if (g_manager) {
g_manager->stopAll();
}
exit(0);
}
}
int main() {
ProcessManager manager;
g_manager = &manager;
// 注冊信號處理器
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
// ... 配置和啟動進程 ...
manager.startMonitoring();
// 保持運行
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
進階特性
日志記錄
為了更好地追蹤進程狀態(tài),可以添加日志功能:
class Logger {
public:
static void log(const std::string& level, const std::string& message) {
auto now = std::chrono::system_clock::now();
auto time = std::chrono::system_clock::to_time_t(now);
std::cout << "[" << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S")
<< "] [" << level << "] " << message << std::endl;
}
static void info(const std::string& message) { log("INFO", message); }
static void warn(const std::string& message) { log("WARN", message); }
static void error(const std::string& message) { log("ERROR", message); }
};
健康檢查
實現(xiàn)進程健康檢查機制:
struct HealthCheck {
std::string type; // "http", "tcp", "script"
std::string target;
int interval; // 檢查間隔(秒)
int timeout; // 超時時間(秒)
};
// 在ProcessConfig中添加
HealthCheck healthCheck;
資源限制
使用setrlimit限制進程資源:
void setProcessLimits() {
struct rlimit limit;
// 限制內(nèi)存
limit.rlim_cur = 512 * 1024 * 1024; // 512MB
limit.rlim_max = 1024 * 1024 * 1024; // 1GB
setrlimit(RLIMIT_AS, &limit);
// 限制CPU時間
limit.rlim_cur = 3600; // 1小時
limit.rlim_max = 7200; // 2小時
setrlimit(RLIMIT_CPU, &limit);
}
性能優(yōu)化建議
- 使用epoll監(jiān)控進程: 對于大量進程,使用epoll而不是輪詢可以提高效率
- 進程池管理: 預(yù)創(chuàng)建進程池以減少啟動時間
- 配置文件支持: 使用JSON或YAML配置文件管理進程配置
- 進程分組: 將相關(guān)進程分組管理,支持按組啟動停止
- 優(yōu)雅重啟: 實現(xiàn)熱重啟功能,避免服務(wù)中斷
常見問題與解決方案
問題1: 進程啟動失敗
原因: 可執(zhí)行文件路徑錯誤、權(quán)限不足、依賴庫缺失
解決方案:
- 驗證可執(zhí)行文件路徑和權(quán)限
- 使用
ldd檢查依賴庫 - 添加詳細的錯誤日志
問題2: 僵尸進程
原因: 父進程未及時調(diào)用waitpid回收子進程
解決方案:
// 注冊SIGCHLD信號處理器
signal(SIGCHLD, [](int) {
int status;
while (waitpid(-1, &status, WNOHANG) > 0);
});
問題3: 循環(huán)依賴
原因: 進程依賴關(guān)系配置錯誤
解決方案:
- 在啟動前進行依賴關(guān)系檢查
- 使用拓撲排序檢測循環(huán)依賴
- 提供清晰的錯誤提示
總結(jié)
本文詳細介紹了如何使用C++開發(fā)一個功能完整的多進程管理器,涵蓋了進程順序啟動、優(yōu)雅停止和崩潰自動重啟等核心功能。通過合理的架構(gòu)設(shè)計和實現(xiàn),我們可以構(gòu)建一個穩(wěn)定可靠的進程管理系統(tǒng)。
在實際應(yīng)用中,可以根據(jù)具體需求進一步擴展功能,如添加Web界面、集成監(jiān)控告警、支持分布式部署等。希望本文能夠為你的項目開發(fā)提供有價值的參考。
附錄: 完整源代碼
ProcessManager.h
#ifndef PROCESS_MANAGER_H
#define PROCESS_MANAGER_H
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <thread>
#include <mutex>
#include <atomic>
#include <chrono>
#include <sys/types.h>
// 進程配置結(jié)構(gòu)
struct ProcessConfig {
std::string name; // 進程名稱
std::string executable; // 可執(zhí)行文件路徑
std::vector<std::string> args; // 啟動參數(shù)
int startDelay; // 啟動延遲(毫秒)
int maxRestarts; // 最大重啟次數(shù)
bool autoRestart; // 是否自動重啟
std::vector<std::string> dependencies; // 依賴的進程
ProcessConfig() : startDelay(0), maxRestarts(3), autoRestart(true) {}
};
// 進程狀態(tài)枚舉
enum class ProcessState {
STOPPED, // 已停止
STARTING, // 啟動中
RUNNING, // 運行中
STOPPING, // 停止中
CRASHED // 已崩潰
};
// 進程信息結(jié)構(gòu)
struct ProcessInfo {
ProcessConfig config;
pid_t pid;
ProcessState state;
int restartCount;
std::chrono::system_clock::time_point lastStartTime;
std::chrono::system_clock::time_point lastCrashTime;
ProcessInfo() : pid(-1), state(ProcessState::STOPPED), restartCount(0) {}
};
// 進程管理器類
class ProcessManager {
public:
ProcessManager();
~ProcessManager();
// 添加進程配置
bool addProcess(const ProcessConfig& config);
// 啟動所有進程
bool startAll();
// 啟動指定進程
bool startProcess(const std::string& name);
// 停止所有進程
void stopAll();
// 停止指定進程
bool stopProcess(const std::string& name);
// 獲取進程狀態(tài)
ProcessState getProcessState(const std::string& name) const;
// 啟動監(jiān)控線程
void startMonitoring();
// 停止監(jiān)控線程
void stopMonitoring();
private:
// 按依賴順序排序進程
std::vector<std::string> getStartOrder();
// 實際啟動進程
pid_t launchProcess(ProcessInfo& info);
// 監(jiān)控進程狀態(tài)
void monitorProcesses();
// 重啟崩潰的進程
void restartProcess(const std::string& name);
// 檢查進程是否存活
bool isProcessAlive(pid_t pid);
std::map<std::string, ProcessInfo> processes_;
mutable std::mutex mutex_;
std::atomic<bool> running_;
std::thread monitorThread_;
};
#endif // PROCESS_MANAGER_H
ProcessManager.cpp
#include "ProcessManager.h"
#include <iostream>
#include <algorithm>
#include <signal.h>
#include <sys/wait.h>
#include <unistd.h>
ProcessManager::ProcessManager() : running_(false) {
}
ProcessManager::~ProcessManager() {
stopMonitoring();
stopAll();
}
bool ProcessManager::addProcess(const ProcessConfig& config) {
std::lock_guard<std::mutex> lock(mutex_);
if (processes_.find(config.name) != processes_.end()) {
std::cerr << "Process " << config.name << " already exists" << std::endl;
return false;
}
ProcessInfo info;
info.config = config;
info.pid = -1;
info.state = ProcessState::STOPPED;
info.restartCount = 0;
processes_[config.name] = info;
return true;
}
std::vector<std::string> ProcessManager::getStartOrder() {
std::vector<std::string> order;
std::map<std::string, int> inDegree;
std::map<std::string, std::vector<std::string>> graph;
// 初始化入度
for (const auto& pair : processes_) {
inDegree[pair.first] = 0;
}
// 構(gòu)建依賴圖
for (const auto& pair : processes_) {
const std::string& name = pair.first;
const auto& deps = pair.second.config.dependencies;
for (const auto& dep : deps) {
if (processes_.find(dep) == processes_.end()) {
std::cerr << "Dependency not found: " << dep << std::endl;
return std::vector<std::string>();
}
graph[dep].push_back(name);
inDegree[name]++;
}
}
// 拓撲排序
std::vector<std::string> queue;
for (const auto& pair : inDegree) {
if (pair.second == 0) {
queue.push_back(pair.first);
}
}
while (!queue.empty()) {
std::string current = queue.back();
queue.pop_back();
order.push_back(current);
for (const auto& next : graph[current]) {
inDegree[next]--;
if (inDegree[next] == 0) {
queue.push_back(next);
}
}
}
// 檢查是否有循環(huán)依賴
if (order.size() != processes_.size()) {
std::cerr << "Circular dependency detected!" << std::endl;
order.clear();
}
return order;
}
pid_t ProcessManager::launchProcess(ProcessInfo& info) {
pid_t pid = fork();
if (pid < 0) {
std::cerr << "Failed to fork process: " << info.config.name << std::endl;
return -1;
}
if (pid == 0) {
// 子進程
std::vector<char*> argv;
argv.push_back(const_cast<char*>(info.config.executable.c_str()));
for (auto& arg : info.config.args) {
argv.push_back(const_cast<char*>(arg.c_str()));
}
argv.push_back(nullptr);
execv(info.config.executable.c_str(), argv.data());
// 如果execv返回,說明執(zhí)行失敗
std::cerr << "Failed to execute: " << info.config.executable << std::endl;
exit(1);
}
// 父進程
return pid;
}
bool ProcessManager::startProcess(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
std::cerr << "Process not found: " << name << std::endl;
return false;
}
ProcessInfo& info = it->second;
if (info.state == ProcessState::RUNNING) {
std::cout << "Process already running: " << name << std::endl;
return true;
}
// 檢查依賴進程是否已啟動
for (const auto& dep : info.config.dependencies) {
auto depIt = processes_.find(dep);
if (depIt == processes_.end() ||
depIt->second.state != ProcessState::RUNNING) {
std::cerr << "Dependency not running: " << dep << std::endl;
return false;
}
}
info.state = ProcessState::STARTING;
// 啟動延遲
if (info.config.startDelay > 0) {
std::this_thread::sleep_for(
std::chrono::milliseconds(info.config.startDelay));
}
pid_t pid = launchProcess(info);
if (pid < 0) {
info.state = ProcessState::STOPPED;
return false;
}
info.pid = pid;
info.state = ProcessState::RUNNING;
info.lastStartTime = std::chrono::system_clock::now();
std::cout << "Started process: " << name << " (PID: " << pid << ")" << std::endl;
return true;
}
bool ProcessManager::startAll() {
std::vector<std::string> order = getStartOrder();
if (order.empty()) {
return false;
}
for (const auto& name : order) {
if (!startProcess(name)) {
std::cerr << "Failed to start process: " << name << std::endl;
return false;
}
}
return true;
}
bool ProcessManager::stopProcess(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
return false;
}
ProcessInfo& info = it->second;
if (info.state != ProcessState::RUNNING) {
return true;
}
info.state = ProcessState::STOPPING;
// 發(fā)送SIGTERM信號
if (kill(info.pid, SIGTERM) == 0) {
// 等待進程優(yōu)雅退出
int status;
pid_t result = waitpid(info.pid, &status, WNOHANG);
if (result == 0) {
// 進程還在運行,等待一段時間
std::this_thread::sleep_for(std::chrono::seconds(5));
// 再次檢查
result = waitpid(info.pid, &status, WNOHANG);
if (result == 0) {
// 強制終止
std::cout << "Force killing process: " << name << std::endl;
kill(info.pid, SIGKILL);
waitpid(info.pid, &status, 0);
}
}
}
info.pid = -1;
info.state = ProcessState::STOPPED;
std::cout << "Stopped process: " << name << std::endl;
return true;
}
void ProcessManager::stopAll() {
// 按照啟動順序的反序停止進程
std::vector<std::string> order = getStartOrder();
std::reverse(order.begin(), order.end());
for (const auto& name : order) {
stopProcess(name);
}
}
bool ProcessManager::isProcessAlive(pid_t pid) {
if (pid <= 0) {
return false;
}
int status;
pid_t result = waitpid(pid, &status, WNOHANG);
if (result == 0) {
// 進程仍在運行
return true;
} else if (result == pid) {
// 進程已退出
return false;
} else {
// 錯誤
return false;
}
}
void ProcessManager::restartProcess(const std::string& name) {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
return;
}
ProcessInfo& info = it->second;
// 檢查重啟次數(shù)限制
if (info.restartCount >= info.config.maxRestarts) {
std::cerr << "Max restart count reached for: " << name << std::endl;
info.state = ProcessState::STOPPED;
return;
}
info.restartCount++;
info.lastCrashTime = std::chrono::system_clock::now();
std::cout << "Restarting process: " << name
<< " (attempt " << info.restartCount << ")" << std::endl;
// 等待一小段時間再重啟,避免快速重啟循環(huán)
std::this_thread::sleep_for(std::chrono::seconds(1));
info.state = ProcessState::STARTING;
pid_t pid = launchProcess(info);
if (pid > 0) {
info.pid = pid;
info.state = ProcessState::RUNNING;
info.lastStartTime = std::chrono::system_clock::now();
std::cout << "Restarted process: " << name << " (PID: " << pid << ")" << std::endl;
} else {
info.state = ProcessState::CRASHED;
std::cerr << "Failed to restart process: " << name << std::endl;
}
}
void ProcessManager::monitorProcesses() {
while (running_) {
std::this_thread::sleep_for(std::chrono::seconds(1));
std::vector<std::string> crashedProcesses;
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto& pair : processes_) {
ProcessInfo& info = pair.second;
if (info.state == ProcessState::RUNNING) {
if (!isProcessAlive(info.pid)) {
std::cerr << "Process crashed: " << pair.first << std::endl;
info.state = ProcessState::CRASHED;
if (info.config.autoRestart) {
crashedProcesses.push_back(pair.first);
}
}
}
}
}
// 在鎖外重啟進程,避免死鎖
for (const auto& name : crashedProcesses) {
restartProcess(name);
}
}
}
void ProcessManager::startMonitoring() {
if (!running_) {
running_ = true;
monitorThread_ = std::thread(&ProcessManager::monitorProcesses, this);
}
}
void ProcessManager::stopMonitoring() {
if (running_) {
running_ = false;
if (monitorThread_.joinable()) {
monitorThread_.join();
}
}
}
ProcessState ProcessManager::getProcessState(const std::string& name) const {
std::lock_guard<std::mutex> lock(mutex_);
auto it = processes_.find(name);
if (it == processes_.end()) {
return ProcessState::STOPPED;
}
return it->second.state;
}
main.cpp (基本示例)
#include "ProcessManager.h"
#include <iostream>
#include <csignal>
ProcessManager* g_manager = nullptr;
void signalHandler(int signal) {
if (signal == SIGINT || signal == SIGTERM) {
std::cout << "\nReceived shutdown signal..." << std::endl;
if (g_manager) {
g_manager->stopAll();
}
exit(0);
}
}
int main() {
ProcessManager manager;
g_manager = &manager;
// 注冊信號處理器
signal(SIGINT, signalHandler);
signal(SIGTERM, signalHandler);
// 配置數(shù)據(jù)庫進程
ProcessConfig dbConfig;
dbConfig.name = "database";
dbConfig.executable = "/usr/bin/postgres";
dbConfig.args = {"-D", "/var/lib/postgresql/data"};
dbConfig.startDelay = 0;
dbConfig.maxRestarts = 3;
dbConfig.autoRestart = true;
// 配置應(yīng)用服務(wù)進程(依賴數(shù)據(jù)庫)
ProcessConfig appConfig;
appConfig.name = "app_server";
appConfig.executable = "/opt/myapp/server";
appConfig.args = {"--port", "8080"};
appConfig.startDelay = 2000; // 等待數(shù)據(jù)庫啟動
appConfig.maxRestarts = 5;
appConfig.autoRestart = true;
appConfig.dependencies = {"database"};
// 配置Web服務(wù)進程(依賴應(yīng)用服務(wù))
ProcessConfig webConfig;
webConfig.name = "web_server";
webConfig.executable = "/usr/sbin/nginx";
webConfig.args = {"-c", "/etc/nginx/nginx.conf"};
webConfig.startDelay = 1000;
webConfig.maxRestarts = 3;
webConfig.autoRestart = true;
webConfig.dependencies = {"app_server"};
// 添加進程配置
manager.addProcess(dbConfig);
manager.addProcess(appConfig);
manager.addProcess(webConfig);
// 啟動所有進程
if (manager.startAll()) {
std::cout << "All processes started successfully" << std::endl;
} else {
std::cerr << "Failed to start some processes" << std::endl;
return 1;
}
// 啟動監(jiān)控線程
manager.startMonitoring();
std::cout << "Process manager is running. Press Ctrl+C to stop..." << std::endl;
// 保持運行
while (true) {
std::this_thread::sleep_for(std::chrono::seconds(1));
}
return 0;
}
CMakeLists.txt (編譯配置)
cmake_minimum_required(VERSION 3.10)
project(ProcessManager)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# 添加編譯選項
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pthread")
# 源文件
set(SOURCES
ProcessManager.cpp
main.cpp
)
# 頭文件
set(HEADERS
ProcessManager.h
)
# 創(chuàng)建可執(zhí)行文件
add_executable(process_manager ${SOURCES} ${HEADERS})
# 鏈接pthread庫
target_link_libraries(process_manager pthread)
編譯和運行
# 創(chuàng)建構(gòu)建目錄 mkdir build cd build # 運行CMake cmake .. # 編譯 make # 運行 ./process_manager
Makefile (簡單編譯方式)
CXX = g++ CXXFLAGS = -std=c++11 -Wall -Wextra -pthread TARGET = process_manager SOURCES = ProcessManager.cpp main.cpp HEADERS = ProcessManager.h OBJECTS = $(SOURCES:.cpp=.o) .PHONY: all clean all: $(TARGET) $(TARGET): $(OBJECTS) $(CXX) $(CXXFLAGS) -o $@ $^ %.o: %.cpp $(HEADERS) $(CXX) $(CXXFLAGS) -c $< -o $@ clean: rm -f $(OBJECTS) $(TARGET) run: $(TARGET) ./$(TARGET)
使用說明
編譯項目:
make
運行管理器:
./process_manager
停止管理器: 按 Ctrl+C 或發(fā)送 SIGTERM 信號
注意事項
需要在Linux環(huán)境下編譯運行
確保有足夠的權(quán)限啟動配置的進程
根據(jù)實際需求修改進程配置
可執(zhí)行文件路徑必須是絕對路徑
建議在生產(chǎn)環(huán)境中添加更完善的錯誤處理和日志記錄
以上就是使用C++設(shè)計開發(fā)一個功能完善的多進程管理器的詳細內(nèi)容,更多關(guān)于C++多進程管理器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用CMake構(gòu)建一個簡單的C++項目的實現(xiàn)
CMake是一個跨平臺的自動化構(gòu)建工具,可以用于構(gòu)建各種類型的項目,本文主要介紹了使用CMake構(gòu)建一個簡單的C++項目,具有一定的參考價值,感興趣的可以了解一下2023-10-10
使用C/C++調(diào)用libcurl調(diào)試消息的方式
在使用 C/C++ 調(diào)用 libcurl 進行 HTTP 請求時,有時我們需要查看請求的/應(yīng)答消息的內(nèi)容(包括請求頭和請求體)以方便調(diào)試,libcurl 提供了多種方法來捕獲和輸出這些信息,本文介紹具體的使用方式,需要的朋友可以參考下2025-02-02
Ubuntu中使用VS Code與安裝C/C++插件的教程詳解
這篇文章主要介紹了Ubuntu中使用VS Code與安裝C/C++插件的教程詳解,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
C++實現(xiàn)教職工管理系統(tǒng)課程設(shè)計
這篇文章主要為大家詳細介紹了C++實現(xiàn)教職工管理系統(tǒng)課程設(shè)計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03

