Linux系统编程——09-linux-day06(进程间通信)

在学习Linux系统编程总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

09-linux-day06(进程间通信)

 

 

一、学习目标

1、熟练使用pipe进行父子进程间通信

2、熟练使用pipe进行兄弟进程间通信

3、熟练使用fifo进行无血缘关系的进程间通信

4、熟练掌握mmap函数的使用

5、掌握mmap创建匿名映射区的方法

6、使用mmap进行有血缘关系的进程间通信

7、使用mmap进行无血缘关系的进程间通信

 

二、进程通信


》IPC方法:进程间通信,通过内核提供的缓冲区进行数据交换的机制。


Linux环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间。任何一个进程的全局变量在另一个进程中都看不到,所以进程和进程之间不能相互访问,要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走,内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。
 Linux系统编程——09-linux-day06(进程间通信)_第1张图片
在进程间完成数据传递需要借助操作系统提供特殊的方法,如:文件、管道、信号、共享内存、消息队列、套接字、命名管道等。随着计算机的蓬勃发展,一些方法由于自身设计缺陷被淘汰或者弃用。现今常用的进程间通信方式有:

1)pipe 管道 (使用最简单)
2)fifo 信号 (开销最小)
3)mmap 共享映射区 (无血缘关系) 速度最快
4)本地socket 本地套接字 (最稳定)
5)信号(携带信息量最小)
6)共享内存
7)消息队列



1、管道的概念

管道是一种最基本的IPC机制,作用于有血缘关系的进程之间,完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质:
1. 其本质是一个伪文件(实为内核缓冲区)
2. 由两个文件描述符引用,一个表示读端,一个表示写端。
3. 规定数据从管道的写端流入管道,从读端流出。
管道的原理: 管道实为内核使用环形队列机制,借助内核缓冲区(4k)实现。
管道的局限性:
① 数据一旦被读走,便不在管道中存在,不可反复读取。
②由于管道采用半双工通信方式。因此,数据只能在一个方向上流动。
③ 只能在有公共祖先的进程间使用管道。

常见的通信方式有,单工通信、半双工通信、全双工通信。
 

2、管道通信举例

man pipe

int pipe(int pipefd[2]);

  pipefd读写文件描述符,0代表读,1代表写

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

>touch pipe.c

>vi pipe.c

 1 #include
 2 #include
 3 
 4 int main()
 5 {
 6     int fd[2];
 7     pipe(fd);
 8     pid_t pid = fork();
 9     
10     if(pid == 0){
11         //son
12         sleep(3);
13         write(fd[1],"hello",5);
14     }
15     else if(pid > 0){
16         //parent
17         char buf[12]={0};
18         int ret = read(fd[0],buf,sizeof(buf));//read会等待write写
19         if(ret > 0){
20             write(STDOUT_FILENO,buf,ret);
21         }
22     }
23     return 0;
24 }

>make

>./pipe

 

3、父子进程实现ps、grep命令

>touch pipe_ps.c

>vi pipe_ps.c

 1 #include
 2 #include
 3 
 4 int main()
 5 {
 6     int fd[2];
 7     pipe(fd);
 8     pid_t pid = fork();
 9     
10     if(pid == 0){
11         //son
12         //son --> ps
13         //1.先重定向
14         dup2(fd[1],STDOUT_FILENO);//标准输出重定向到管道写端
15         //2.execlp
16         execlp("ps","ps","aux",NULL);
17     }
18     else if(pid > 0){
19         //parent
20         //1.先重定向,标准输入重定向到管道读端
21         dup2(fd[0],STDIN_FILENO);
22         //2.execlp
23         execlp("grep","grep","bash",NULL);//grep bash等待标准输入
24     }
25     return 0;
26 }

>make

>./pipe_ps

 

4、ps、grep命令实现问题解决

代码的问题:父进程认为还有写端存在,就有可能还有人给发数据,继续等待。

Linux系统编程——09-linux-day06(进程间通信)_第2张图片

>vi pipe_ps.c

 1 #include
 2 #include
 3 
 4 int main()
 5 {
 6     int fd[2];
 7     pipe(fd);
 8     pid_t pid = fork();
 9     
10     if(pid == 0){
11         //son
12         //son --> ps
13         //关闭读端
14         close(fd[0]);
15         //1.先重定向
16         dup2(fd[1],STDOUT_FILENO);//标准输出重定向到管道写端
17         //2.execlp
18         execlp("ps","ps","aux",NULL);
19     }
20     else if(pid > 0){
21         //parent
22         //关闭写端
23         close(fd[1]);
24         //1.先重定向,标准输入重定向到管道读端
25         dup2(fd[0],STDIN_FILENO);
26         //2.execlp
27         execlp("grep","grep","bash",NULL);//grep bash等待标准输入
28     }
29     return 0;
30 }

>make

>./pipe_ps

 

5、管道的读写行为

读管道:

  写端全部关闭——read读到0,相当于读到文件末尾

  写端没有全部关闭

    有数据——read 读到数据

    没有数据——read 阻塞 ,fcntl 函数可以更改非阻塞

写管道:

  读端全部关闭——?产生一个信号SIGPIPE,程序异常终止

  读端未全部关闭

    管道已满——write阻塞。如果要显示现象,读端一直不读,写端狂写。

    管道未满——write正常写入

 

6、管道大小和优劣

》计算管道大小

long fpathconf(int fd, int name);

ulimit -a

》优缺点

优点:简单

缺点:1)只能有血缘关系的进程通信;2)父子进程单方向通信,如果需要双向通信,需要创建多根管道。

  

 

7、fifo实现通信写端

 

 

8、fifo使用注意事项

 

 

9、mmap映射开始

 

 

 

 

 

 

在学习Linux系统编程总结了笔记,并分享出来。有问题请及时联系博主:Alliswell_WP,转载请注明出处。

你可能感兴趣的:(Linux系统编程——09-linux-day06(进程间通信))