一、需求
(1)父子进程存在继承关系,即子进程拷贝自父进程;
(2)同时运行进程个数可控;
二、实现
(1)创建进程池,控制运行的进程个数;
(2)封装Fork()接口,创建子进程;当进程池满载后,等待进程池进程运行结束退出后,再创建子进程;
三、源码
(1)process_manage.h
/**
*****************************************************************************
* Copyright (C), 2023-2024
*
* @file process_manage.h
* @brief control processes
*
*
* @author sbinhuang
* @date 2023-07-02
* @version v1.0.0 20230702
*----------------------------------------------------------------------------
* @note 历史版本 修改人员 修改日期 修改内容
* @note v1.0 sbinhuang 2023-07-02 1.创建
*
*****************************************************************************
*/
#ifndef SELF_UTILITY_PROCESS_MANAGE_H_
#define SELF_UTILITY_PROCESS_MANAGE_H_
#include <sys/types.h>
#include <unistd.h>
#include <stdint.h>
#include <vector>
namespace SelfUtility {
class ProcessManage {
public:
// default one child process
ProcessManage();
// Set number of processes
bool ProcessConstraint(unsigned int number);
// creates a new process by duplicating the calling process
// On success, the PID of the child process is returned in the parent, and
// 0 is returned in the child
pid_t Fork();
// wait all process finish
bool WaitAllProcess();
// get current process id
static pid_t CurrentProcessId();
// get virtual memory peak(kb)
static uint64_t VmPeak();
// get current virtual memory size(kb)
static uint64_t CurrentVm();
// get resident memory size(kb)
static uint64_t CurrentRSS();
private:
std::vector<pid_t> _process_list;
}; // ProcessManage
} // SelfUtility
#endif // SELF_UTILITY_PROCESS_MANAGE_H_
(2) process_manage.cpp
/**
*****************************************************************************
* Copyright (C), 2023-2024
*
* @file process_manage.cpp
* @brief control processes
*
*
* @author sbinhuang
* @date 2023-07-02
* @version v1.0.0 20230702
*----------------------------------------------------------------------------
* @note 历史版本 修改人员 修改日期 修改内容
* @note v1.0 sbinhuang 2023-07-02 1.创建
*
*****************************************************************************
*/
#include "process_manage.h"
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fstream>
#include <vector>
#include <string>
#include "messages.h"
using SelfUtility::ProcessManage;
// default one child process
ProcessManage::ProcessManage() {
_process_list.resize(1, 0);
}
// Set number of processes
bool ProcessManage::ProcessConstraint(unsigned int number) {
if (number == 0) return false;
_process_list.resize(number, 0);
return true;
}
// creates a new process by duplicating the calling process
// On success, the PID of the child process is returned in the parent, and
// 0 is returned in the child
pid_t ProcessManage::Fork() {
std::size_t idx = 0;
std::size_t process_list_size = _process_list.size();
// get variable process
while (1) {
idx = 0;
for (; idx < process_list_size; ++idx) {
pid_t pid = _process_list[idx];
if (pid == 0) break; // unused
int status = 0;
pid_t ret = waitpid(pid, &status, WNOHANG);
if (0 == ret) continue; // specify process is run
break; // specify process is finish
}
if (idx < process_list_size) break; // availiable
sleep(1); // wait
}
// creat child process
pid_t pid = fork();
while (pid == -1) {
// fork failed, wait 1 second and try against
pid = fork();
sleep(1);
}
if (pid == 0) return pid; // child process
// parent process
_process_list[idx] = pid;
return pid;
}
// wait all process finish
bool ProcessManage::WaitAllProcess() {
std::size_t idx = 0;
std::size_t process_list_size = _process_list.size();
for (; idx < process_list_size; ++idx) {
pid_t pid = _process_list[idx];
if (0 == pid) continue; // unused
int status = 0;
waitpid(pid, &status, 0);
}
return true;
}
// get current process id
pid_t ProcessManage::CurrentProcessId() {
return getpid();
}
// get virtual memory peak(kb)
uint64_t ProcessManage::VmPeak() {
pid_t pid = getpid();
std::string file_name("/proc/");
file_name.append(std::to_string(pid));
file_name.append("/status");
std::ifstream in_file(file_name, std::ios::in);
if (!in_file.is_open()) {
LOG_ERROR("File open failed!(%s)\n", file_name.c_str());
exit(-1);
}
// VmPeak: 20620 kB
// VmSize: 20620 kB
// VmRSS: 3948 kB
uint64_t memory_size = 0;
std::string line;
while (getline(in_file, line)) {
if (line.size() == 0) continue;
std::size_t pos = line.find("VmPeak:");
if (pos == std::string::npos) continue;
std::string substr(line.substr(pos + 7));
pos = substr.find_first_not_of(" \t\r");
if (pos == std::string::npos) {
LOG_ERROR("File format error!(%s: %s)\n", file_name.c_str(),
line.c_str());
exit(-1);
}
substr.erase(0, pos);
pos = substr.find("kB");
if (pos == std::string::npos) {
LOG_ERROR("File format error!(%s: %s)\n", file_name.c_str(),
line.c_str());
exit(-1);
}
substr.erase(pos);
pos = substr.find_last_not_of(" \t\r");
substr.erase(pos);
memory_size = std::atoll(substr.c_str());
}
if (in_file.is_open()) in_file.close();
return memory_size;
}
// get current virtual memory size(kb)
uint64_t ProcessManage::CurrentVm() {
pid_t pid = getpid();
std::string file_name("/proc/");
file_name.append(std::to_string(pid));
file_name.append("/status");
std::ifstream in_file(file_name, std::ios::in);
if (!in_file.is_open()) {
LOG_ERROR("File open failed!(%s)\n", file_name.c_str());
exit(-1);
}
// VmPeak: 20620 kB
// VmSize: 20620 kB
// VmRSS: 3948 kB
uint64_t memory_size = 0;
std::string line;
while (getline(in_file, line)) {
if (line.size() == 0) continue;
std::size_t pos = line.find("VmSize:");
if (pos == std::string::npos) continue;
std::string substr(line.substr(pos + 7));
pos = substr.find_first_not_of(" \t\r");
if (pos == std::string::npos) {
LOG_ERROR("File format error!(%s: %s)\n", file_name.c_str(),
line.c_str());
exit(-1);
}
substr.erase(0, pos);
pos = substr.find("kB");
if (pos == std::string::npos) {
LOG_ERROR("File format error!(%s: %s)\n", file_name.c_str(),
line.c_str());
exit(-1);
}
substr.erase(pos);
pos = substr.find_last_not_of(" \t\r");
substr.erase(pos);
memory_size = std::atoll(substr.c_str());
}
if (in_file.is_open()) in_file.close();
return memory_size;
}
// get resident memory size(kb)
uint64_t CurrentRSS() {
pid_t pid = getpid();
std::string file_name("/proc/");
file_name.append(std::to_string(pid));
file_name.append("/status");
std::ifstream in_file(file_name, std::ios::in);
if (!in_file.is_open()) {
LOG_ERROR("File open failed!(%s)\n", file_name.c_str());
exit(-1);
}
// VmPeak: 20620 kB
// VmSize: 20620 kB
// VmRSS: 3948 kB
uint64_t memory_size = 0;
std::string line;
while (getline(in_file, line)) {
if (line.size() == 0) continue;
std::size_t pos = line.find("VmRSS:");
if (pos == std::string::npos) continue;
std::string substr(line.substr(pos + 7));
pos = substr.find_first_not_of(" \t\r");
if (pos == std::string::npos) {
LOG_ERROR("File format error!(%s: %s)\n", file_name.c_str(),
line.c_str());
exit(-1);
}
substr.erase(0, pos);
pos = substr.find("kB");
if (pos == std::string::npos) {
LOG_ERROR("File format error!(%s: %s)\n", file_name.c_str(),
line.c_str());
exit(-1);
}
substr.erase(pos);
pos = substr.find_last_not_of(" \t\r");
substr.erase(pos);
memory_size = std::atoll(substr.c_str());
}
if (in_file.is_open()) in_file.close();
return memory_size;
}
四、参考文档
(1)工具库编译参考文档
工具库编译参考