【linux之进程间通信】——管道

目录

进程间是怎么通信的

管道

匿名管道

匿名管道是如何实现进程间通信

内核角度理解匿名管道

管道的读写规则

 情景1

情景2

 情景3

​ 情景4

命名管道

创建命名管道

命令行方式创建

函数创建

命名管道的应用场景 

场景1

 场景2

场景3


进程间是怎么通信的

之前我们说过,进程与进程之间是相互独立的,它们的数据也是绝对独立的,那么如果一个进程要向另一个进程发送数据,就需要借助第三方资源,这个第三方资源必须让这两个进程都能看到,且通信的时候,互不影响对方,在内核中,有几种方式能够实现进程通信,今天要讲的是管道

管道

所谓的管道,是内存中的一个缓存文件,进程A在管道写入数据,实际是写入到内核中的缓存文件中,进程B从管道中读取数据,实际是从内核的缓存文件中读取数据。

 管道的传输数据是单向的,只能由一个进程写入,一个进程读出

匿名管道

概念
匿名管道是没有名字的,它是特殊文件,它只创建在内存中,不存在我们磁盘中,即用完就销毁了。

#include<unistd.h>

int pipe(int fd[2]);

功能:在内核中创建一个匿名管道

参数:

fd:文件描述符数组,其中将f[0]存储读端的文件描述符,fd[1]存储写端的文件描述符。

返回值:成功返回0,失败返回-1.

 匿名管道一般适用于有血缘关系之间的通信,例如父子进程,兄弟进程 等       

匿名管道是如何实现进程间通信

1.父进程利用pipe创建出一个匿名管道,得到的文件表示符指向管道的读端和写端

2.利用fork生成一个子进程,子进程的文件描述符也指向管道的读端和写端。

3.关闭父进程的读端和关闭子进程的写端 或者 关闭父进程的写端和关闭子进程的读端。

这样匿名管道就创建完成。

ps aux | grep myfile 

我们知道“ | ”这也是一个管道,它其实也是一个匿名管道,上面这条命令是将ps 进程输出的数据输送到管道中,然后将grep从管道中读取数据,并查找myfile文件,然后将结果打印到屏幕上

 

 内核角度理解匿名管道

当父进程创建子进程的时候,系统会给子进程创建file_struct和file的数据结构,然后将父进程的file_struct和file的中数据拷贝给子进程的的file_struct和file,这样父进程和子进程就能够指向同一个管道。

代码:

 

管道的读写规则

 情景1

让子进程一直往管道中写入数据,父进程的读端不关闭,但不读取数据。 

 

结果 

刚开始,子进程一直往管道中写入数据,当管道写满之后,则子进程就不会往管道中写入数据,子进程就被阻塞等待,等父进程来读取数据时,子进程才会被运行起来。如图所示:

那么我们既然知道管道是有大小的,我们来测试一下我这个版本的linux管道大小是多少。

此时的父进程还是在睡眠,不读取数据。

输出结果: 

 

当输出到65536的时候,则不在屏幕上打印数据,则说明子进程往管道写入的数据已满,所以我这个版本的linux的匿名管道的大小为65536个字节。

情景2

当子进程往管道中写入一定的数据后,就不再往管道中写入数据,并让父进程一直读取管道中的数据。

子进程 

父进程: 

 当子进程只往管道中写入数据时,而父进程不断的往管道中读取数据,当父进程将管道中的数据读完之后,则父进程就会被阻塞等待,直到子进程往管道中写数据时,父进程才会读取管道中的数据。

 

 情景3

当子进程往管道中写完数据后就关闭写端,父进程一直在读取.

 结果:

子进程往管道中写入三条数据,同时父进程将这三条数据给读取上来,子进程关闭写端后,父进程去读取数据时,read读不到数据,并返回0。

 情景4

当子进程一直往管道中写数据,父进程休息5秒后关闭读端。        

 

结果:

前5秒上显示器打了5条 i am child,直到第5秒,父进程的读端关闭后,子进程就被系统给杀掉了,不在打印i am child。

总结:

1.当管道中没数据的时候,读端的进程就会被阻塞等待(前提写端没有关闭)。

2.当管道中的数据被写满的时候,写端就会被阻塞等待(前提读端没有关闭)。

3.当写端关闭的时候,读端把数据读完之后,则在读取数据时,read会返回0.

4.当读端关闭的时候,写端的进程会自动的被操作系统给杀掉。

5.半双工通信,只能有一端写入,一端读取。

命名管道

匿名管道是通过子进程能够继承父进程的pcb,file和file_struct等结构体,使父子进程(兄弟进程等有血缘关系的进程)能够看到同一个管道,可是两个没有任何的关系进程是没办法这种方式看到同一个管道的。然而系统有命名管道可以让这两个不同的进程看到同一个管道,实现通信。

我们可以在磁盘中创建一个管道文件,当要通信的时候,不同的进程以不同的读或写的方式往磁盘上打开这个管道文件,然后将这个管道文件加载到缓存内核中,然后一个进程往内核中的管道文件中写数据,另一个进程就往内核中的管道文件中读数据,原理是跟匿名管道是类似的。命名管道跟匿名管道一样,读端在管道内读多少,就会删除多少。

命名管道是存在磁盘上,它是有文件名的,命名管道让不同的进程在同一路劲下打开命名管道,然后进行通信,它们在内存所写的数据不会刷新到磁盘上。它的存在只是为了让进程能够通过路径找到这个管道文件,然后实现通信

创建命名管道

命令行方式创建

mkfifo pipe

在磁盘上创建一个名字为pipe的命名管道。

命名管道的文件属性是p。

函数创建

int mkfifo(const char *filename,mode_t mode);

filename:创建管道的文件名

mode:管道的权限属性

返回值:成功返回0,失败返回-1.

命名管道的应用场景 

场景1

利用命名管道实现一个进程对另一个进程的通信 

思路:client进程从键盘读取到的数据传输到命名管道上,然后server进程再去从命名管道中读取数据,然后将信息打印到屏幕上。 

头文件:

makefile文件:

client.c文件:

 server.c文件

 运行结果:

 场景2

一个进程利用命名管道给另一个进程输入某个指令,让该进程执行该指令。

 client.c文件

 server.c文件

运行结果: 

场景3

用命名管道实现文件拷贝

思路:进程A读取myfile文件的内容,然后将这些数据写到管道中,进程B创建出一个新文件myfile_1,然后进程B从管道中读取数据并写入到新文件myfile_1中,直到结束。

client.c文件 

server.c 文件

管道的特点:

1.一般而言,进程退出,管道释放,管道的生命周期是随进程的。

2.一般而言,内核会对管道操作进行同步和互斥。

3.管道是半双工的,只能有一个方向流动,需要双方通信的时候,是会建立起两个管道。

  好啦,今天的内容就分享到这里,喜欢的读者给个三连呗,感谢你的支持。

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Linux下,进程间通信的一种方式是通过共享内存来实现的。共享内存允许两个或多个进程共享一定的存储区,这样它们就可以直接访问同一块内存区域,而不需要进行数据的复制。共享内存是一种高效的进程间通信方式,因为数据直接写入内存,不需要多次数据拷贝,所以传输速度很快\[2\]。 在使用共享内存进行进程间通信时,需要给共享内存创建一个唯一的身份ID,以便区分不同的共享内存。当进程需要访问共享内存时,需要在映射时带上这个ID,这样就可以确定访问的是哪一个共享内存\[3\]。 需要注意的是,共享内存并没有提供同步机制,也就是说,在一个进程结束对共享内存的写操作之前,并没有自动机制可以阻止另一个进程开始对它进行读取。为了实现多个进程对共享内存的同步访问,通常会使用信号量来实现对共享内存的同步访问控制\[2\]。 总结起来,Linux下的共享内存是一种高效的进程间通信方式,允许多个进程共享一块存储区。通过给共享内存创建唯一的身份ID,可以区分不同的共享内存。然而,共享内存并没有提供同步机制,需要使用信号量来实现对共享内存的同步访问控制\[2\]\[3\]。 #### 引用[.reference_title] - *1* *3* [Linux进程间通信——共享内存实现](https://blog.csdn.net/zhm1949/article/details/124909541)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Linux进程间通信方式——共享内存](https://blog.csdn.net/xujianjun229/article/details/118584955)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值