C++中实现子进程执行和管道通信详解

 更新时间:2024年01月08日 09:14:20   作者:Silent_Blue_Sky  
在这篇博客中,我们将深入探索如何在 C++ 程序中实现子进程的创建与执行,以及父子进程间的管道通信,感兴趣的小伙伴可以跟随小编一起学习一下

简介

在这篇博客中,我们将深入探索如何在 C++ 程序中实现子进程的创建与执行,以及父子进程间的管道通信。核心代码提供了一个框架,用于接收用户命令、创建子进程并利用 execvp 系统调用执行这些命令。此外,我们通过创建管道(pipe),展示了如何在父子进程间安全地传递数据。

本文重点介绍 fork, pipe, 和 execvp 的使用方法,并解释了如何将标准输出和标准错误从子进程重定向到父进程。这一过程涉及对 Unix 系统调用的深入理解,尤其是进程间通信(IPC)的概念。我们的目标是提供一个清晰的指南,帮助读者理解和实现在现代操作系统中广泛应用的进程创建、执行和通信机制。

该教程适合对操作系统、进程管理以及 Unix/Linux 系统编程感兴趣的读者。无论是系统编程新手还是有经验的开发者,都可以通过这个实例加深对进程间通信和命令行界面(CLI)应用编程的理解。

exec相关

一共有六个分三组记忆

execlp -> execvp
execl  -> execv
execle  -> execve

这几个函数的速记

记忆口诀如下:

0、exec是通用前缀

1、 p 代表第一个参数是file 也就是程序的名字比如 ls, 如果名字没带p, 代表第一个参数是path, 比如 /bin/ls

2、 l 代表参数传递的是list, 参数是一个个传递的,最后一个参数为NULL

3、 v 代表argv, 参数是用char* 数组传递的

4、 e 代表环境变量

execlp  l->list,p-> file          参数就是(file, a1, a2, a3,..., NULL);
execvp  v->argv,p->file.          参数就是file, aegv)
execl   l->list,没p -> path       参数就是(path, a1, a2, a3, ..., NULL);
execv   v->argv,没p->path         参数(path, argv);
execle  l->list,没p->path, e->env 参数(path, a0, a1, ..., NULL, env);
execve  v->aegv,没p->path, e->env 参数(path, argv, env);

实战代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <iostream>
#include <string>

bool isCommandSupport(std::string command) {
    if (command == "ls" || command == "pwd" || command == "ps" || command == "cat" || command == "grep" ||
        command == "wc" || command == "exit") {
        return true;
    }
    return false;
}

void childTask() {
    while (true) {
        // 获得一整行输入
        std::string line;
        size_t len = 0;
        std::getline(std::cin, line);
        // 进行分割
        char *p = strtok((char *) line.c_str(), " ");
        char *argv[100];
        int argc = 0;
        while (p != NULL) {
            argv[argc++] = p;
            p = strtok(NULL, " ");
        }
        argv[argc] = NULL;
        if (argc == 0) {
            continue;
        }
        if (isCommandSupport(argv[0])) {
            if (strcmp(argv[0], "exit") == 0) {
                exit(0);
            }
        } else {
            printf("command not support\n");
            continue;
        }
        int pipefd[2];
        pid_t pid;
        char buf;
        if (pipe(pipefd) == -1) {
            perror("pipe");
            exit(EXIT_FAILURE);
        }

        pid = fork();
        if (pid == -1) {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        if (pid == 0) {    /* 子进程 */
            close(pipefd[0]);          // 关闭读端
            dup2(pipefd[1], STDOUT_FILENO); // 将标准输出重定向到管道写端
            dup2(pipefd[1], STDERR_FILENO); // 将标准错误也重定向到管道写端
            close(pipefd[1]);          // 关闭原始写端
            execvp(argv[0], argv);
            _exit(EXIT_FAILURE);
        } else {          /* 父进程 */
            close(pipefd[1]);          // 关闭写端
            while (read(pipefd[0], &buf, 1) > 0) {
                write(STDOUT_FILENO, &buf, 1);
            }
            close(pipefd[0]);          // 关闭读端
            int status;
            waitpid(pid, &status, 0);
            if (WIFEXITED(status)) {
            } else if (WIFSIGNALED(status)) {
                printf("child terminated abnormally, signal %d\n", WTERMSIG(status));
            }
        }
    }
}

int main() {
   childTask();
}

到此这篇关于C++中实现子进程执行和管道通信详解的文章就介绍到这了,更多相关C++子进程执行和管道通信内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言经典指针笔试题详解

    C语言经典指针笔试题详解

    今天博主来讲解4道经典的指针笔试题,很多朋友没有深刻理解函数传参知识都会在这些题目上出错,下面话不多说,我们开始
    2021-10-10
  • 一文带你学习C++中的派生机制

    一文带你学习C++中的派生机制

    C++是一门面向对象的编程语言,其中的派生机制是其重要的面向对象特性之一。本文我们就来详细地学习一下C++中的派生机制的相关知识吧
    2023-04-04
  • 解决VC++编译报错error C2248的方案

    解决VC++编译报错error C2248的方案

    这篇文章主要介绍了解决VC++编译报错error C2248的方案的相关资料,需要的朋友可以参考下
    2015-11-11
  • Visual Studio Code (vscode) 配置C、C++环境/编写运行C、C++的教程详解(主要Windows、简要Linux)

    Visual Studio Code (vscode) 配置C、C++环境/编写运行C、C++的教程详解(主要Windo

    这篇文章主要介绍了Visual Studio Code (vscode) 配置C、C++环境/编写运行C、C++(主要Windows、简要Linux),本文通过实例截图给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • C/C++中如何判断某一文件或目录是否存在

    C/C++中如何判断某一文件或目录是否存在

    以下文章是对C/C++中判断某一文件或目录是否存在的实现代码进行了详细的分析介绍,需要的朋友可以参考下
    2013-07-07
  • C++中std::optional的使用指南分享

    C++中std::optional的使用指南分享

    C++ 17 引入了std::optional,表示一个可能有值的对象,这篇文章主要来和大家聊聊std::optional的使用,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-06-06
  • 在Ubuntu中安装VSCode并配置C/C++开发环境的方法步骤

    在Ubuntu中安装VSCode并配置C/C++开发环境的方法步骤

    这篇文章主要介绍了在Ubuntu中安装VSCode并配置C/C++开发环境的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • C++实现KFC点餐系统

    C++实现KFC点餐系统

    这篇文章主要为大家详细介绍了C++实现KFC点餐系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-07-07
  • 详解C语言中函数宏的三种封装方式

    详解C语言中函数宏的三种封装方式

    函数宏,即包含多条语句的宏定义,其通常为某一被频繁调用的功能的语句封装,且不想通过函数方式封装来降低额外的弹栈压栈开销。本文就来聊聊函数宏的三种封装方式吧
    2023-03-03
  • C/C++的关键字之static你了解吗

    C/C++的关键字之static你了解吗

    这篇文章主要为大家详细介绍了C/C++的关键字之static,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02

最新评论