实现在任意个程序之间创建管道

本文介绍了一个程序,用于在多个程序间创建管道并执行,实现实时数据交换而非串行执行。通过a、b、c三个测试程序,展示了进程间通过管道进行通信的过程,包括时间戳输出以观察各步骤的顺序。

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

实验目的:

实现一个程序,执行格式为:./proc command1 … commandn

作用是在参数中指定的程序之间创建管道并执行这些程序

实验原理:

循环的为两个程序之间创建管道并执行前一个程序:

+-------------+-------------+-------------+-------------+

|       p1      |       p2      |       ….     |       pn      |

+-------------+-------------+-------------+-------------+

                    ⬆                 ⬆                  ⬆

                   ①               ②                ③

主进程会fork出一个子进程:

主进程:为自己的标准输出创建管道并连到写端,主进程的工作已完成,可以将自己替换为p1并执行

子进程:将自己的标准输入连到主进程创建的管道的读端

此时①处应做的操作已经完成,p2相当于p1,可以循环执行

在③处的管道创建完成之后,就只需要将当前进程替换为pn并执行

测试:

有三个程序用于测试:

a:分别向标准输出输出三个字符ABC,并在输出之间睡眠一段时间以便观察

b:从标准输入循环读取字符并随即向标准输出输出字符

c:从标准输入循环读取字符并随即向标准输出输出字符

为得到三个进程每一步操作的顺序,在每一次写字符和读字符的时候都获取当前系统的时间并通过标准错误流输出

实验结果:

#write time 1544673891.433610#
#inter time 1544673891.589610#
#read time 1544673891.592173#
>Read>>
#read time 1544673891.595636#
I
#read time 1544673891.596860#
n
#read time 1544673891.598782#
t
#read time 1544673891.602652#
e
#read time 1544673891.603777#
r
#read time 1544673891.604423#
>
#read time 1544673891.606588#
A
#write time 1544673893.435466#
#inter time 1544673893.439350#
#read time 1544673893.441641#
B
#write time 1544673895.440165#
#inter time 1544673895.443178#
#read time 1544673895.445848#
C
#write time 1544673900.444004#

可以很明显的看出,进程在运行期间通过管道交流,而不是后一个进程等待前一个执行结束之后才可以开始执行

注意事项:

在测试程序中执行输出的时候,需要在输出之后fflush()一下,否则输出的内容可能会被暂时缓冲起来而不立即输出,造成前一个程序执行结束后面的程序才能读到的假象。进程的缓冲策略可以被设置。

源代码:

https://github.com/biaoJM/shell-pipe-simulate

<think>好的,用户想要在Linux环境下用C语言编写一个实现有名管道双向通信的程序,并且要使用线程。我得先理清楚有名管道的基本概念和线程的使用方法。 首先,有名管道(FIFO)是一种可以在无关进程之间通信的机制,通过文件系统中的一个特殊文件来传输数据。不过这里用户提到的是双向通信,而传统的FIFO通常是半双工的,也就是只能单向传输。所以可能需要创建两个FIFO,一个用于A到B,另一个用于B到A的通信。 接下来是关于线程的部分。程序需要同时处理读取和写入操作,使用多线程可以让这两个操作并发执行,避免阻塞。主线程可能负责创建子线程,一个线程处理发送数据,另一个处理接收数据。 然后需要确定程序的结构。每个进程(比如客户端和服务器)都需要创建两个FIFO,一个读,一个写。比如,进程A写入FIFO1,进程B读取FIFO1;进程B写入FIFO2,进程A读取FIFO2。这样就能实现双向通信了。 不过用户可能希望单个程序同时处理两个方向的通信,所以可能需要在一个程序中同时打开两个FIFO,分别用于读和写。这时候要注意打开的顺序,避免阻塞。比如,以读写模式打开FIFO可能会需要正确的O_NONBLOCK标志处理,防止open调用阻塞。 接下来考虑线程的创建。主程序创建两个线程,一个负责不断读取数据,另一个负责等待用户输入并发送数据。线程函数需要处理各自的文件描述符,确保读写操作正确同步。 然后需要考虑FIFO的创建和清理。程序启动时要检查FIFO是否存在,如果不存在则创建程序结束时可能需要删除这些FIFO文件,避免残留。 另外,错误处理也很重要。比如,打开FIFO失败的情况,或者读写时出现错误,应该适当处理,比如关闭文件描述符,打印错误信息,然后退出。 最后,测试程序可能需要同时运行两个实例,或者一个作为服务端,一个作为客户端。需要确保两个FIFO的路径正确,权限设置合适,避免权限问题导致无法读写。 可能遇到的问题包括:FIFO的阻塞模式导致线程挂起,需要正确设置非阻塞标志;线程之间的同步,比如使用互斥锁保护共享资源;还有缓冲区的大小,确保数据能正确传输而不溢出。 总结下来,程序的步骤大概是: 1. 创建两个FIFO文件。 2. 打开各自的读写文件描述符。 3. 创建两个线程,分别处理发送和接收。 4. 线程函数中循环读取输入或接收数据。 5. 处理结束信号,关闭文件描述符并删除FIFO。 需要提醒用户注意FIFO的打开顺序,避免死锁,比如两个程序同时尝试以只读或只写模式打开FIFO,导致双方都阻塞。另外,使用线程时要注意资源的管理,避免竞态条件。</think>在Linux环境下使用C语言实现有名管道(FIFO)双向通信的程序,可以通过以下步骤完成: ### 一、实现思路 1. **创建两个FIFO**:分别用于A→B和B→A的通信 2. **使用多线程**:一个线程负责发送数据,另一个线程负责接收数据 3. **非阻塞IO**:避免读写操作阻塞程序运行 4. **双工通信**:每个程序都需要同时具备读写能力 ### 二、完整代码示例 ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <pthread.h> #define FIFO1 "/tmp/fifo1" #define FIFO2 "/tmp/fifo2" #define BUFFER_SIZE 1024 int fd_write, fd_read; // 发送线程函数 void *send_thread(void *arg) { char buffer[BUFFER_SIZE]; while(1) { fgets(buffer, BUFFER_SIZE, stdin); write(fd_write, buffer, BUFFER_SIZE); } return NULL; } // 接收线程函数 void *recv_thread(void *arg) { char buffer[BUFFER_SIZE]; while(1) { int n = read(fd_read, buffer, BUFFER_SIZE); if(n > 0) { printf("Received: %s", buffer); } } return NULL; } int main(int argc, char *argv[]) { pthread_t tid1, tid2; // 创建FIFO mkfifo(FIFO1, 0666); mkfifo(FIFO2, 0666); // 根据参数决定通信方向 if(argc > 1 && argv[1][0] == '1') { fd_write = open(FIFO1, O_WRONLY); fd_read = open(FIFO2, O_RDONLY | O_NONBLOCK); } else { fd_write = open(FIFO2, O_WRONLY); fd_read = open(FIFO1, O_RDONLY | O_NONBLOCK); } // 创建线程 pthread_create(&tid1, NULL, send_thread, NULL); pthread_create(&tid2, NULL, recv_thread, NULL); // 等待线程结束 pthread_join(tid1, NULL); pthread_join(tid2, NULL); // 清理资源 close(fd_write); close(fd_read); unlink(FIFO1); unlink(FIFO2); return 0; } ``` ### 三、使用说明 1. 编译程序: ```bash gcc fifo_chat.c -o chat -lpthread ``` 2. 在两个终端分别运行: ```bash # 终端1(模式1) ./chat 1 # 终端2(模式2) ./chat ``` 3. 输入任意内容即可实现双向通信 ### 四、关键点说明 1. **FIFO创建**: - `mkfifo()` 创建命名管道 - 0666权限设置允许所有用户访问 2. **非阻塞模式**: - `O_NONBLOCK`标志确保读操作不会阻塞线程 - 写端保持阻塞模式保证数据完整性 3. **线程管理**: - 发送线程持续监听标准输入 - 接收线程持续监听管道输入 4. **双工实现**: - 程序根据启动参数选择通信方向 - 每个实例同时维护读/写两个管道 ### 五、注意事项 1. 程序退出时会自动删除FIFO文件 2. 输入内容不要超过1024字节 3. 使用Ctrl+C终止程序时需要处理信号 4. 实际应用中需要添加错误检查代码 这个实现展示了Linux环境下使用C语言和线程实现双向管道通信的基本方法,可以根据具体需求扩展错误处理和业务逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值