Windows/Linux双端实战:手把手教你用C++和Boost.Process写一个进程管理器
Windows/Linux双端实战手把手教你用C和Boost.Process写一个进程管理器在开发跨平台应用时进程管理是一个常见但颇具挑战性的需求。无论是系统监控工具、自动化测试框架还是服务管理程序都需要对进程进行创建、监控和终止操作。本文将带你从零开始使用C和Boost.Process库构建一个能在Windows和Linux上运行的进程管理器。1. 环境准备与项目搭建1.1 安装必要的开发工具在开始编码前我们需要确保开发环境配置正确Windows平台Visual Studio 2019或更高版本安装vcpkg包管理工具通过vcpkg安装Boost库vcpkg install boost:x64-windowsLinux平台GCC 9或更高版本通过包管理器安装Boost开发包sudo apt-get install libboost-all-dev1.2 创建CMake项目使用CMake可以简化跨平台项目的构建过程。以下是基本的CMakeLists.txt配置cmake_minimum_required(VERSION 3.10) project(ProcessManager) set(CMAKE_CXX_STANDARD 17) find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system) add_executable(process_manager src/main.cpp src/process_manager.cpp include/process_manager.h ) target_link_libraries(process_manager PRIVATE Boost::filesystem Boost::system )2. 进程管理核心功能实现2.1 进程枚举功能在Windows和Linux上获取进程列表的方式截然不同Windows实现使用Toolhelp32Snapshot APIstd::vectorProcessInfo enumerate_processes_win() { std::vectorProcessInfo processes; HANDLE snapshot CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (snapshot INVALID_HANDLE_VALUE) { return processes; } PROCESSENTRY32 process_entry; process_entry.dwSize sizeof(PROCESSENTRY32); if (Process32First(snapshot, process_entry)) { do { ProcessInfo info; info.pid process_entry.th32ProcessID; info.name process_entry.szExeFile; processes.push_back(info); } while (Process32Next(snapshot, process_entry)); } CloseHandle(snapshot); return processes; }Linux实现通过/proc文件系统std::vectorProcessInfo enumerate_processes_linux() { std::vectorProcessInfo processes; namespace fs boost::filesystem; fs::path proc(/proc); for (const auto entry : fs::directory_iterator(proc)) { if (!fs::is_directory(entry)) continue; try { int pid std::stoi(entry.path().filename().string()); fs::path status_file entry.path() / status; if (fs::exists(status_file)) { std::ifstream file(status_file.string()); std::string line; ProcessInfo info; info.pid pid; while (std::getline(file, line)) { if (line.find(Name:) 0) { info.name line.substr(6); boost::trim(info.name); break; } } processes.push_back(info); } } catch (...) { continue; } } return processes; }2.2 进程状态检查检查进程是否运行也需要平台特定的实现Windows实现bool is_process_running_win(int pid) { HANDLE process OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); if (process NULL) { return false; } DWORD exit_code; if (GetExitCodeProcess(process, exit_code)) { CloseHandle(process); return exit_code STILL_ACTIVE; } CloseHandle(process); return false; }Linux实现bool is_process_running_linux(int pid) { std::string proc_path /proc/ std::to_string(pid); return boost::filesystem::exists(proc_path); }3. 使用Boost.Process进行跨平台抽象Boost.Process提供了跨平台的进程管理接口我们可以基于它构建统一的API3.1 启动进程ProcessResult start_process(const std::string command, const std::vectorstd::string args) { ProcessResult result; try { boost::process::ipstream out_stream; boost::process::ipstream err_stream; boost::process::child child( command, boost::process::args(args), boost::process::std_out out_stream, boost::process::std_err err_stream ); std::string line; while (child.running() std::getline(out_stream, line)) { result.output line \n; } while (std::getline(err_stream, line)) { result.error line \n; } child.wait(); result.exit_code child.exit_code(); result.success result.exit_code 0; } catch (const boost::process::process_error e) { result.error e.what(); result.success false; } return result; }3.2 终止进程bool terminate_process(int pid) { try { boost::process::child child(pid); child.terminate(); return true; } catch (...) { return false; } }4. 构建完整的进程管理器类现在我们可以将所有功能整合到一个统一的类中class ProcessManager { public: ProcessManager() { #ifdef _WIN32 m_platform Platform::Windows; #else m_platform Platform::Linux; #endif } std::vectorProcessInfo enumerate_processes() { switch (m_platform) { case Platform::Windows: return enumerate_processes_win(); case Platform::Linux: return enumerate_processes_linux(); default: return {}; } } bool is_process_running(int pid) { switch (m_platform) { case Platform::Windows: return is_process_running_win(pid); case Platform::Linux: return is_process_running_linux(pid); default: return false; } } ProcessResult start_process(const std::string command, const std::vectorstd::string args {}) { return ::start_process(command, args); } bool terminate_process(int pid) { return ::terminate_process(pid); } private: enum class Platform { Windows, Linux }; Platform m_platform; };5. 测试与验证编写测试代码验证我们的进程管理器int main() { ProcessManager manager; // 枚举所有进程 auto processes manager.enumerate_processes(); std::cout Running processes:\n; for (const auto proc : processes) { std::cout PID: proc.pid \tName: proc.name \n; } // 启动一个测试进程 std::cout \nStarting notepad/gedit...\n; auto result manager.start_process( #ifdef _WIN32 notepad.exe #else gedit #endif ); if (!result.success) { std::cerr Failed to start process: result.error \n; return 1; } // 检查进程状态 int test_pid 1; // 替换为实际获取的PID if (manager.is_process_running(test_pid)) { std::cout Process test_pid is running\n; } else { std::cout Process test_pid is not running\n; } // 终止进程 if (manager.terminate_process(test_pid)) { std::cout Successfully terminated process test_pid \n; } else { std::cout Failed to terminate process test_pid \n; } return 0; }在实际项目中我发现处理进程路径时需要特别注意平台差异。Windows下可执行文件通常需要.exe后缀而Linux则不需要。此外Linux下/proc文件系统提供了丰富的进程信息但解析时需要考虑各种边界情况。