进程间通信(ipc):管道 信号量 共享内存 消息队列 套接字
1、管道
管道如果为空,或者管道写满了,写会阻塞。
重点:
管道文件是在内存中分配空间,管道文件有一个读端,一个写端。
管道分为:有名管道和无名管道。有名管道可以在任意两个进程之间通信,无名管道只能在父子进程之间使用;
**通信方式:**半双工
有名管道:
1、mkffo FIFO
2、系统调用
管道文件 前面有个p prw-rw-r-- 1 stu stu 0 11月 1 19:20 fifo
**1、**mkffo FIFO
stu@stu-virtual-machine:~$ ls
公共的 模板 视频 图片 文档 下载 音乐 桌面 snap Test
stu@stu-virtual-machine:~$ mkfifo fifo
stu@stu-virtual-machine:~$ ls
公共的 模板 视频 图片 文档 下载 音乐 桌面 fifo snap Test
stu@stu-virtual-machine:~$ ls -l
总用量 40
drwxr-xr-x 2 stu stu 4096 9月 9 17:47 公共的
drwxr-xr-x 2 stu stu 4096 9月 9 17:47 模板
drwxr-xr-x 2 stu stu 4096 9月 9 17:47 视频
drwxr-xr-x 2 stu stu 4096 10月 18 23:02 图片
drwxr-xr-x 2 stu stu 4096 9月 9 17:47 文档
drwxr-xr-x 2 stu stu 4096 9月 9 17:47 下载
drwxr-xr-x 2 stu stu 4096 9月 9 17:47 音乐
drwxr-xr-x 3 stu stu 4096 9月 20 22:34 桌面
prw-rw-r-- 1 stu stu 0 11月 1 19:20 fifo
drwx------ 3 stu stu 4096 10月 10 17:26 snap
drwxrwxr-x 10 stu stu 4096 10月 30 10:55 Test
读写两个进程必须同时进行,否则将不能正常运行:要使用两个终端来打开这连个进程。
读进程:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<fcntl.h>
4 #include<unistd.h>
5 #include<string.h>
6 #include<assert.h>
7 int main()
8 {
9 int fwr =open("fifo",O_RDONLY);
10 assert(fwr!=-1);
11
12 printf("fwr=%d\n",fwr);
13 while(1)
14 {
15 char buff[128] = {0};
16 int n =read(fwr,buff,127);
17 if(n==0)
18 {
19 break;
20 }
21 printf("buff=%s,n=%d\n",buff,n);
22 }
23 close(fwr);
24 exit(0);
25
26 }
写程序:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<fcntl.h>
4 #include<unistd.h>
5 #include<string.h>
6 #include<assert.h>
7 #include<signal.h>
8 void sig_fun(int sig)
9 {
10 printf("sig=%d\n",sig);
11 }
12 int main()
13 {
14 signal(SIGPIPE,sig_fun);
15 int fwd =open("fifo",O_WRONLY);//必须有读和写两个进程才能运行。
16 assert(fwd!=-1);
17 printf("fwd=%d\n",fwd);
18 char buff[128]={0};
19 while(strncmp(buff,"end",3)!=0)
20 {
21 memset(buff,0,128);
22 printf("input:\n");
23 fgets(buff,128,stdin);
24 write(fwd,buff,strlen(buff));
25 }
26 /*
27 while(1)
28 {
29 memset(buff,0,128);
30 printf("input:\n");
31 fgets(buff,128,stdin);
32 if(strncmp(buff,"end",3)==0)
33 {
34 break;
35 }
36 write(fwd,buff,strlen(buff));
37 }
38
39 */
40 close(fwd);
41 exit(0);
42 }
**2、**系统调用
stu@stu-virtual-machine:~/Test/管道举例$ ps -ef | grep bash
stu 2827 2710 0 19:19 pts/0 00:00:00 bash
stu 3930 2827 0 19:53 pts/0 00:00:00 grep --color=auto bash
**无名管道:**pipe
只能在父子进程间使用,pipe(fd)会创造两个文件描述符,用来描述无名管道的读端和写端。
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<fcntl.h>
4 #include<unistd.h>
5 #include<string.h>
6 #include<assert.h>
7 #include<signal.h>
8 void sig_fun(int sig)
9 {
10 printf("sig=%d\n",sig);
11 }
12 int main()
13 {
14 int fd[2];//fd[0]读 fd[1]写
15 int res =pipe(fd);
16 assert(res!=-1);
17
18 pid_t pid =fork();
19 assert(pid!=-1);
20
21 if(pid==0)
22 {
23 close(fd[1]);
24 char buff[128] ={0};
25 read(fd[0],buff,127);
26 printf("child read:%s\n",buff);
27 close(fd[0]);
28 }
29 else
30 {
31 close(fd[0]);
32 char buff[128] ={0};
33 fgets(buff,128,stdin);
34
35 write(fd[1],buff,strlen(buff));
36 close(fd[1]);
37 }
38 exit(0);
39 }
stu@stu-virtual-machine:~/Test/管道举例$ ./无名管道
其温泉温泉温泉温泉温泉
child read:其温泉温泉温泉温泉温泉
[1],buff,strlen(buff));
36 close(fd[1]);
37 }
38 exit(0);
39 }
```bash
stu@stu-virtual-machine:~/Test/管道举例$ ./无名管道
其温泉温泉温泉温泉温泉
child read:其温泉温泉温泉温泉温泉