请选择 进入手机版 | 继续访问电脑版
MSIPO技术圈 首页 IT技术 查看内容

工具库2:封装一个进程控制库(linux)

2023-07-13

一、需求

(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)工具库编译参考文档
工具库编译参考

相关阅读

热门文章

    手机版|MSIPO技术圈 皖ICP备19022944号-2

    Copyright © 2024, msipo.com

    返回顶部