进程间通信(四)——popen函数

popen函数用于创建管道并启动子进程执行shell命令,实现进程间通信。通过指定"r"或"w"参数,父进程可以读取或写入子进程的输入/输出。在读模式下,子进程的标准输出进入管道供父进程读取;在写模式下,父进程写入管道作为子进程的输入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

popen函数

通过管道与shell命令进行通信

  • popen函数
    • FILE *popen(const char *command, const char *type);
    • 创建一个管道,并创建一个子进程来执行shell,shell会创建一个子进程来执行command
    • 将父子进程的输入/输出重定向到管道,建立一个单向的数据流
    • 返回一个fp文件指针给父进程,父进程可根据fp对管道进行读写
    • 向管道中读数据,读命令的标准输入
    • 向管道中写数据,写入该命令的标准输入

使用popen函数,建立起读模式、写模式就好

  • 读模式调用popen
    • popen(command, "r");
    • popen函数创建输入写入到管道,被调用popen来的父进程读取
    • 子进程的标准输出写入到管道,被调用popen的父进程读取
    • 父进程通过对popen返回的fp指针读管道,获取执行命令的输出
  • 写模式调用popen
    • fp = popen(command, "w");
    • popen函数创建子进程执行command,创建管道
    • 调用popen的父进程,通过fp进行对管道进行写操作
    • 写入的内容通过管道传给子进程,作为子进程的输入
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#i
### 实现管道通信的程序 在 Linux 环境下,可以通过 `pipe` 函数来创建匿名管道并实现进程间的通信。下面是一个完整的代码示例,展示如何通过匿名管道实现父子进程之间的数据传递。 #### 单向管道通信示例 以下代码展示了父进程向子进程发送消息的过程: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main() { int pipefd[2]; // 用于存储管道文件描述符 char buffer[100]; pid_t pid; if (pipe(pipefd) == -1) { // 创建管道 perror("Pipe failed"); return EXIT_FAILURE; } pid = fork(); // 创建子进程 if (pid < 0) { // 如果fork失败 perror("Fork failed"); return EXIT_FAILURE; } if (pid > 0) { // 父进程逻辑 close(pipefd[0]); // 关闭读端 const char *msg = "Hello from parent!"; write(pipefd[1], msg, strlen(msg)+1); // 向管道写入数据 close(pipefd[1]); wait(NULL); // 等待子进程结束 } else { // 子进程逻辑 close(pipefd[1]); // 关闭写端 read(pipefd[0], buffer, sizeof(buffer)); // 从管道读取数据 printf("Child received: %s\n", buffer); close(pipefd[0]); } return EXIT_SUCCESS; } ``` 上述代码实现了简单的单向通信功能[^1]。父进程将字符串 `"Hello from parent!"` 写入管道,而子进程则负责从管道中读取消息并打印出来。 --- #### 双向管道通信示例 如果需要实现双向通信,则可以使用两个管道分别处理输入和输出方向的数据流。以下是具体实现方式: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main() { int pipefd1[2], pipefd2[2]; // 定义两组管道 char buffer[100]; pid_t pid; if (pipe(pipefd1) == -1 || pipe(pipefd2) == -1) { // 创建两条管道 perror("Pipe failed"); return EXIT_FAILURE; } pid = fork(); if (pid < 0) { // 错误检测 perror("Fork failed"); return EXIT_FAILURE; } if (pid > 0) { // 父进程逻辑 close(pipefd1[0]); // 关闭第一个管道的读端 close(pipefd2[1]); // 关闭第二个管道的写端 const char *parent_msg = "Message from Parent"; write(pipefd1[1], parent_msg, strlen(parent_msg)+1); read(pipefd2[0], buffer, sizeof(buffer)); printf("Parent received: %s\n", buffer); close(pipefd1[1]); close(pipefd2[0]); wait(NULL); } else { // 子进程逻辑 close(pipefd1[1]); // 关闭第一个管道的写端 close(pipefd2[0]); // 关闭第二个管道的读端 read(pipefd1[0], buffer, sizeof(buffer)); printf("Child received: %s\n", buffer); const char *child_msg = "Response from Child"; write(pipefd2[1], child_msg, strlen(child_msg)+1); close(pipefd1[0]); close(pipefd2[1]); } return EXIT_SUCCESS; } ``` 此代码片段演示了更复杂的场景——父子进程能够相互收发消息[^2]。其中一条管道 (`pipefd1`) 负责父进程向子进程传输数据;另一条管道 (`pipefd2`) 则反向操作。 --- #### 使用 `popen` 和 `pclose` 除了手动管理管道外,还可以利用标准库函数 `popen` 来简化某些特定用途下的管道编程工作流程。例如调用外部命令并将结果返回给当前应用程序: ```c #include <stdio.h> #include <stdlib.h> int main() { FILE *fp; char path[1024]; fp = popen("ls -l /tmp", "r"); // 执行 ls 命令,并打开只读模式的标准输出重定向 if (fp == NULL) { perror("Failed to run command"); exit(EXIT_FAILURE); } while (fgets(path, sizeof(path), fp) != NULL) { // 循环读取每行输出 printf("%s", path); } pclose(fp); // 关闭管道资源 return EXIT_SUCCESS; } ``` 这里借助于 `popen` 接口轻松完成了对外部工具(如 `ls`)的结果捕获任务[^3]。 --- ### 总结说明 以上三种方法均能有效达成不同层次需求下的管道通讯目标。对于初学者而言建议先熟悉基础概念再逐步深入学习高级技巧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值