C++多进程编程

一、进程介绍

进程是指在操作系统中正在运行的一个程序,它在操作系统中占有一定的资源,如内存、I/O、CPU时间等。

每个进程都有自己的地址空间,互相之间无法访问,是通过操作系统提供的IPC(进程间通信)机制来进行进程间的通信和数据交互。

在C++中,可以通过一些库函数来创建和控制进程的运行,如fork()、exec()、wait()等函数。

二、多进程编程

多进程编程是指同时运行多个进程,它可以提高程序的并发性和效率,对于系统性能和响应时间的要求高时非常有用。

在C++中,创建一个新进程可以使用fork()函数,它会复制父进程的所有资源,包括代码、数据、栈、堆等,然后子进程继续执行fork()函数后的语句,而父进程则返回子进程的进程ID,这样父子进程可以在不同的代码分支中执行不同的任务。

可以通过判断fork()函数的返回值来确定当前代码执行的是父进程还是子进程:

pid_t pid = fork();
if (pid == 0) {
    // 子进程
} else if (pid > 0) {
    // 父进程
} else {
    // 出错处理
}

其中pid_t是一个整型类型,代表进程ID,如果pid等于0,则表示当前代码执行的是子进程的分支;如果pid大于0,则表示当前代码执行的是父进程的分支,pid就是子进程的进程ID;如果pid小于0,则表示创建新进程失败。

除了fork()函数,还可以使用exec系列函数和wait()函数来控制进程的运行。

三、进程间通信

进程间通信(IPC)是指两个或多个进程之间的数据交换和通信,可以使用多种方式进行进程间通信,常见的有管道、消息队列、共享内存和信号量等。

其中,管道是最简单的通信方式,它可以在两个进程之间传递字符流,但只能用于具有亲缘关系的进程之间通信(即通过fork()函数创建的父子进程);消息队列可以传递复杂的数据结构,但如果数据量比较大时会影响性能;共享内存可以实现多个进程之间对同一块内存的访问,但需要解决进程同步和互斥的问题;信号量可以用来实现进程之间的同步和互斥,但需要掌握一定的信号量编程技巧。

下面是一个使用管道在父子进程之间传递数据的例子:

const int BUFFER_SIZE = 1024;
int pipe_fd[2];
char message[BUFFER_SIZE];
pid_t pid;

if (pipe(pipe_fd) < 0) {
    std::cerr << "create pipe error." << std::endl;
    exit(-1);
}

if ((pid = fork()) == -1) {
    std::cerr << "fork error." << std::endl;
    exit(-1);
} else if (pid == 0) {
    close(pipe_fd[1]);    // 关闭写通道
    if (read(pipe_fd[0], message, BUFFER_SIZE) == -1) {
        std::cerr << "read error." << std::endl;
        exit(-1);
    }
    std::cout << "child process received message: " << message << std::endl;
    close(pipe_fd[0]);    // 关闭读通道
} else {
    close(pipe_fd[0]);    // 关闭读通道
    std::string input_message;
    std::cout << "input message to be sent to child process: ";
    std::getline(std::cin, input_message);
    if (write(pipe_fd[1], input_message.c_str(), input_message.size()) == -1) {
        std::cerr << "write error." << std::endl;
        exit(-1);
    }
    close(pipe_fd[1]);    // 关闭写通道
    wait(NULL);           // 等待子进程结束
}

四、进程管理

进程管理是指对操作系统中的进程进行管理和调度,包括创建进程、终止进程、监控进程等操作,常用的进程管理工具有ps、top和kill等。

在C++中,可以使用系统函数kill()来终止一个进程,需要传入进程ID和终止信号:

if (kill(pid, SIGKILL) == -1) {
    std::cerr << "kill process error." << std::endl;
    exit(-1);
}

其中,SIGKILL是一个宏定义,代表终止信号。

五、多进程编程实例

下面是一个简单的多进程ping程序,它可以并行的ping多个IP地址,同时显示结果:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

const int MAX_PROC_NUM = 10;
const int MAX_IP_NUM = 10;
const int MAX_RESULT_SIZE = 1024;

int proc_num = 0;
char ip_list[MAX_IP_NUM][16];

bool ping(const char* ip) {
    char cmd[1024] = {0};
    sprintf(cmd, "ping -c 4 %s", ip);
    FILE* pipe = popen(cmd, "r");
    if (!pipe) {
        return false;
    }

    char buffer[MAX_RESULT_SIZE];
    memset(buffer, 0, MAX_RESULT_SIZE);
    while (!feof(pipe)) {
        if (fgets(buffer, MAX_RESULT_SIZE, pipe)) {
            std::cout << buffer;
        }
    }

    if (pclose(pipe) == -1) {
        return false;
    }

    return true;
}

void handle_signal(int signo) {
    std::cout << "process " << getpid() << " received signal " << signo << std::endl;
    exit(signo);
}

void start_proc(int idx) {
    const char* ip = ip_list[idx];
    std::cout << "start ping " << ip << ", process id " << getpid() << std::endl;

    if (signal(SIGINT, handle_signal) == SIG_ERR) {
        std::cerr << "error setting signal handler." << std::endl;
        exit(-1);
    }

    ping(ip);

    std::cout << "ping " << ip << " finish, process id " << getpid() < 0) {
        std::cout << "process " << pid << " exit with status " << WEXITSTATUS(status) << std::endl;
        proc_num--;
    }
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "usage: " << argv[0] << " ip1 [ip2] [...]" < MAX_IP_NUM) {
        std::cerr << "too many ip addresses." << std::endl;
        return -1;
    }

    for (int i = 0; i < argc - 1; ++i) {
        strncpy(ip_list[i], argv[i + 1], sizeof(ip_list[i]));
    }

    for (int i = 0; i  0) {
            // parent
        } else {
            std::cerr << "fork process error." < 0) {
        check_procs();
        sleep(1);
    }

    return 0;
}

原创文章,作者:小蓝,如若转载,请注明出处:https://www.506064.com/n/235615.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小蓝小蓝
上一篇 2024-12-12 11:56
下一篇 2024-12-12 11:56

相关推荐

  • 如何通过jstack工具列出假死的java进程

    假死的java进程是指在运行过程中出现了某些问题导致进程停止响应,此时无法通过正常的方式关闭或者重启该进程。在这种情况下,我们可以借助jstack工具来获取该进程的进程号和线程号,…

    编程 2025-04-29
  • Java中的僵尸进程简介与解决方法

    本文将对Java中的僵尸进程进行详细阐述,并给出几种解决方法。 一、僵尸进程的概念 在操作系统中,进程是指正在执行的程序。当一个进程创建了一个子进程,而该子进程完成了任务却没有被父…

    编程 2025-04-27
  • 多线程和多进程的应用

    多线程和多进程是现代编程中常用的技术,可以提高程序的效率和性能。本文将从不同的角度对多线程和多进程进行详细的介绍和应用。 一、多线程 vs 多进程 多线程和多进程都是为了实现程序并…

    编程 2025-04-27
  • Python多进程读取数据

    本文将从多个方面详细阐述在Python中如何通过多进程读取数据,并给出完整的代码示例。 一、多进程概述 在计算机科学中,进程是正在执行的程序实例。多进程是指计算机系统同时执行多个进…

    编程 2025-04-27
  • 进程a与进程b共享变量s1

    本文将从多个方面对进程a与进程b共享变量s1做详细的阐述,并给出代码示例。 一、定义全局变量s1 进程a与进程b共享变量s1,意味着s1是一个全局变量。在C语言中,可以使用关键字e…

    编程 2025-04-27
  • python多进程并行循环

    在大数据时代,我们通常需要处理大量的数据。处理大数据往往需要较长的时间,影响效率。Python提供了多线程、多进程等并行处理方式来提高数据处理效率。本文将主要讲解python多进程…

    编程 2025-04-27
  • Python进程池共享内存用法介绍

    本文将从多个方面详细阐述Python进程池共享内存的相关知识,包括如何使用进程池、进程池的实现原理、进程池中的共享内存管理等。本文内容将涵盖: 一、进程池的使用 进程池是一种有效的…

    编程 2025-04-27
  • Linux守护进程

    一、什么是Linux守护进程 Linux守护进程是在Linux系统下运行的一种特殊进程,它没有终端连接,并且在后台运行,通常用于某些服务程序、监控程序或者系统管理程序等。守护进程的…

    编程 2025-04-25
  • Python 进程通信

    当需要在不同进程之间进行通信时,Python 提供了几种方法来实现进程间通信。这些方法包括队列,管道,共享内存以及套接字。 1. 队列 Python 队列是进程安全的,并且可以很方…

    编程 2025-04-24
  • Linux下杀掉进程的命令详解

    一、杀掉进程的概念 在进行Linux系统管理以及软件开发过程中,我们常常需要杀掉卡死或异常程序的进程。杀掉进程是指在运行中的进程突然中断或终止运行,也称为进程终止。 杀掉进程的主要…

    编程 2025-04-24

发表回复

登录后才能评论