Linux进程间通信——命名管道应用实例
发布日期:2021-06-29 12:42:20
浏览次数:2
分类:技术文章
本文共 5554 字,大约阅读时间需要 18 分钟。
命名管道克服了管道没有名字的限制,同时除了具有管道的功能外(也是半双工),它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。
下面程序fifo_write.c周期的往管道中写入数据:
/*============================================================================= # FileName: fifo_write.c# Desc: write data to name pipe# Author: Licaibiao # Version: # LastChange: 2017-01-10 # History: =============================================================================*/ #include#include #include #include #include #include #include #include int main(){ const char *fifo_name = "/tmp/my_fifo"; int pipe_fd = -1; int data_fd = -1; int res = 0; static int i = 0; const int open_mode = O_WRONLY; char buffer[PIPE_BUF + 1]; char test_data[PIPE_BUF]; if(access(fifo_name, F_OK) == -1) { printf ("Create the fifo pipe.\n"); res = mkfifo(fifo_name, 0777); if(res != 0) { fprintf(stderr, "Could not create fifo %s\n", fifo_name); exit(EXIT_FAILURE); } } printf("Process %d opening FIFO O_WRONLY\n", getpid()); pipe_fd = open(fifo_name, open_mode); printf("Process %d result %d\n", getpid(), pipe_fd); if(pipe_fd !=-1) { while(1) { sprintf(test_data,"test number %d \n",i++); printf("Process %d write data to name pipe: %s",getpid(),test_data); res = write(pipe_fd, test_data, PIPE_BUF); if(res == -1) { printf("write error on name pipe !\n"); exit(EXIT_FAILURE); } else { sleep(2); } } } else { exit(EXIT_FAILURE); } close(pipe_fd);}
下面程序fifo_read.c周期的从管道中读取数据:
/*============================================================================= # FileName: fifo_read.c# Desc: read data from name pipe# Author: Licaibiao # Version: # LastChange: 2017-01-10 # History: =============================================================================*/ #include#include #include #include #include #include #include #include int main(){ const char *fifo_name = "/tmp/my_fifo"; int pipe_fd = -1; int res = 0; int open_mode = O_RDONLY; char buffer[PIPE_BUF + 1]; int bytes_read = 0; int bytes_write = 0; memset(buffer, '\0', sizeof(buffer)); printf("Process %d opening FIFO O_RDONLY\n", getpid()); pipe_fd = open(fifo_name, open_mode); printf("Process %d result %d\n",getpid(), pipe_fd); if(pipe_fd != -1) { while(1) { res = read(pipe_fd, buffer, PIPE_BUF); if(res>0) { printf("Process %d read data from name pipe :%s",getpid(),buffer); } sleep(2); } close(pipe_fd); } else { exit(EXIT_FAILURE); } printf("Process %d finished, %d bytes read\n", getpid(), bytes_read); exit(EXIT_SUCCESS);}
编译运行结果为:
root@ubuntu:/home/share/pipe# vim fifo_write.c root@ubuntu:/home/share/pipe# vim fifo_read.c root@ubuntu:/home/share/pipe# gcc fifo_read.c -o fifo_readroot@ubuntu:/home/share/pipe# gcc fifo_write.c -o fifo_writeroot@ubuntu:/home/share/pipe# root@ubuntu:/home/share/pipe# lsfifo_read fifo_read.c fifo_write fifo_write.croot@ubuntu:/home/share/pipe# ./fifo_write &[1] 88963root@ubuntu:/home/share/pipe# Process 88963 opening FIFO O_WRONLYroot@ubuntu:/home/share/pipe# root@ubuntu:/home/share/pipe# ./fifo_read Process 88964 opening FIFO O_RDONLYProcess 88963 result 3Process 88963 write data to name pipe: test number 0 Process 88964 result 3Process 88964 read data from name pipe :test number 0 Process 88963 write data to name pipe: test number 1 Process 88964 read data from name pipe :test number 1 Process 88963 write data to name pipe: test number 2 Process 88964 read data from name pipe :test number 2 Process 88963 write data to name pipe: test number 3 Process 88964 read data from name pipe :test number 3 Process 88963 write data to name pipe: test number 4 Process 88964 read data from name pipe :test number 4 Process 88963 write data to name pipe: test number 5 Process 88964 read data from name pipe :test number 5 ^Croot@ubuntu:/home/share/pipe# Process 88963 write data to name pipe: test number 6 [1]+ Broken pipe ./fifo_writeroot@ubuntu:/home/share/pipe# ls /tmpat-spi2 my_fifo pulse-PKdhtXMmr18n ssh-fbQHGxSG2651 vgauthsvclog.txt.0 vmware-licaibiaokeyring-x9fH8E pulse-2L9K88eMlGn7 pulse-TIYtyXUn5vZV unity_support_test.0 VMwareDnD vmware-rootroot@ubuntu:/home/share/pipe#
先在后台运行write函数,我们可以看到pipe被阻塞了,直到有一个进程读取pipe它才得意继续运行。最后当没有进程读取管道数据时,写入端写入数据将返回错误。另外,我们可以在tmp目录下看到我们创建的管道 my_fifo:
这里总结一下name pipe 需要注意的事项:
1、就是程序不能以O_RDWR(读写)模式打开FIFO文件进行读写操作,而其行为也未明确定义,因为如一个管道以读/写方式打开,进程就会读回自己的输出,同时我们通常使用FIFO只是为了单向的数据传递。
2、就是传递给open调用的是FIFO的路径名,而不是正常的文件。(如:const char *fifo_name = "/tmp/my_fifo"; )
3、第二个参数中的选项O_NONBLOCK,选项O_NONBLOCK表示非阻塞,加上这个选项后,表示open调用是非阻塞的,如果没有这个选项,则表示open调用是阻塞的。
4、关于阻塞问题:
- 对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;如果open调用是非阻塞的的(即第二个参数为O_RDONLY | O_NONBLOCK),则即使没有其他进程以写方式打开同一个FIFO文件,open调用将成功并立即返回。
- 对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;如果open调用是非阻塞的(即第二个参数为O_WRONLY | O_NONBLOCK),open总会立即返回,但如果没有其他进程以只读方式打开同一个FIFO文件,open调用将返回-1,并且FIFO也不会被打开。
5、管道安全问题:
有一种情况是:一个FIFO文件,有多个进程同时向同一个FIFO文件写数据,而只有一个读FIFO进程在同一个FIFO文件中读取数据时,会发生数据块的相互交错。不同进程向一个FIFO读进程发送数据是很普通的情况。这个问题的解决方法,就是让写操作的原子化。系统规定:在一个以O_WRONLY(即阻塞方式)打开的FIFO中, 如果写入的数据长度小于等待PIPE_BUF,那么或者写入全部字节,或者一个字节都不写入。如果所有的写请求都是发往一个阻塞的FIFO的,并且每个写记请求的数据长度小于等于PIPE_BUF字节,系统就可以确保数据决不会交错在一起。
2019.06.24更新
命名管道的一些读写规则:
- 以非阻塞只写方式打开时,在多进程中同时写入数据,注意写入的大小和写入的原子性。
- 以非阻塞只写方式打开时,如果没有一个进程在读管道,打开会失败。
- 以非阻塞只写方式打开时,如果所有读管道进程关闭,写进程会收到SIGPIPE信号如果写进程不对SIGPIPE信号进行处理,会导致写进程退出。
转载地址:https://caibiao-lee.blog.csdn.net/article/details/54320515 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
网站不错 人气很旺了 加油
[***.192.178.218]2024年04月17日 14时48分39秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
无人机破巡检难题,秒变电网卫士
2019-04-29
五年,我成为了一名嵌入式工程师。
2019-04-29
2020年电赛题目,命题专家们怎么看?
2019-04-29
PCB元器件摆放不可忽略的10个技巧
2019-04-29
掌握AI核心技术没有秘籍,能自己创造就是王道
2019-04-29
大学老师的月薪多少?实话实说:4万多一点……
2019-04-29
2020年电赛题目,命题专家权威解析!
2019-04-29
如何掌握“所有”的程序语言?没错,就是所有!
2019-04-29
39岁单身程序员入住养老院
2019-04-29
写论文,这个神器不能少!
2019-04-29
我在哥大读博的五年,万字总结
2019-04-29
本科、硕士、博士,究竟有何区别?
2019-04-29
如果我的实验室也这样布置,那多好。
2019-04-29
现在做硬件工程师还有前途吗?
2019-04-29
用 50 种编程语言写“Hello,World!”
2019-04-29
GD32替换STM32,这些细节一定要知道。
2019-04-29
华为员工离职心声:菊厂15年退休,感恩,让我实现了财务自由!
2019-04-29
春晚上的“拓荒牛”
2019-04-29
嵌入式驱动自学者的亲身感受,有什么建议?
2019-04-29
华为被超越!这家公司成中国最大智能手机制造商,不是小米!
2019-04-29