通信:因為進程有強大獨立性,當想把自己數據交給另一個進程,需要通信。
通信本質:讓不同進程看到相同資源。

匿名管道:管道:通過某種機制傳遞資源(數據),匿名管道只適用于有血緣關系的進程,一般用于父,子進程通信。
a.創建管道
b.創建子進程
c.父,子進程關閉自己不需要的文件描述符
注意:匿名管道提供單向通信,父讀子寫或父寫子讀,若要實現雙向通信,可再創建一個管道。
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{
int _pipefd[2]={-1,-1};
int ret=pipe(_pipefd);
if(ret==-1)
{
perror("pipe");
return 2;
}
pid_t id=fork();
if(id<0)
{
perror("fork");
return 2;
}
else if(id==0)
{
close(_pipefd[0]);
char buf[]="hello world";
int count=5;
while(count--)
{
write(_pipefd[1],buf,strlen(buf));
sleep(1);
}
}
else
{
close(_pipefd[1]);
char buf[1024]={0};
while(1)
{
memset(buf,'\0',sizeof(buf));
ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
if(_size>0)
{
buf[_size]='\0';
printf("buf:%s\n",buf);
}
}
}
return 0;
}運行結果:
使用管道需注意以下四種情況:
1.如果所有指向管道寫端的文件描述符都關閉了,仍然有進程從管道的讀端讀數據,那么管道中剩余的數據都被讀取后,再次read會返回0,就像讀到文件末尾一樣。
1 #include<stdio.h>
2 #include<string.h>
3 #include<unistd.h>
4 #include<sys/types.h>
5 #include<stdlib.h>
6 int main()
7 {
8 int _pipefd[2]={-1,-1};
9 int ret=pipe(_pipefd);
10 if(ret==-1)
11 {
12 perror("pipe");
13 return 2;
14 }
15
16 pid_t id=fork();
17 if(id<0)
18 {
19 perror("fork");
20 return 2;
21 }
22 else if(id==0)
23 {
24 close(_pipefd[0]);
25 char buf[]="hello world";
26 int count=5;
27 int i=0;
28 while(count--)
29 {
30 if(i==3)
31 {
32 printf("I want sleep\n");
33 break;
34 }
35 write(_pipefd[1],buf,strlen(buf));
36 sleep(1);
37 i++;
38 }
39 close(_pipefd[0]);
40 }
41 else
42 {
43 close(_pipefd[1]);
44 char buf[1024]={0};
46 while(1)
47 {
48 memset(buf,'\0',sizeof(buf));
49 ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
50 if(_size>0)
51 {
52 buf[_size]='\0';
53 printf("buf:%s\n",buf);
54 }
55 }
56 }
57 return 0;
58 }運行結果:
2.如果有指向管道寫端的文件描述符沒關閉,持有管道寫端的進程也沒有向管道中寫數據,這時有進程從管道讀端讀數據,那么管道中剩余的數據都被讀取后,再次read會阻塞,直到管道中有數據可讀了才讀取數據并返回。
1 #include<stdio.h>
2 #include<sys/wait.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/types.h>
6 #include<stdlib.h>
7 int main()
8 {
9 int _pipefd[2]={-1,-1};
10 int ret=pipe(_pipefd);
11 if(ret==-1)
12 {
13 perror("pipe");
14 return 2;
15 }
16
17 pid_t id=fork();
18 if(id<0)
19 {
20 perror("fork");
21 return 2;
22 }
23 else if(id==0)
24 {
25 close(_pipefd[0]);
26 char buf[]="hello world";
27 int count=5;
28 int i=0;
29 while(count--)
30 {
31 if(i==3)
32 {
33 printf("I want sleep\n");
34 sleep(10);
35 }
36 write(_pipefd[1],buf,strlen(buf));
37 sleep(1);
38 i++;
39 }
40 close(_pipefd[0]);
41 }
42 else
43 {
44 close(_pipefd[1]);
45 char buf[1024]={0};
46 while(1)
47 {
48 memset(buf,'\0',sizeof(buf));
49 ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
50 if(_size>0)
51 {
52 buf[_size]='\0';
53 printf("buf:%s\n",buf);
54 }
55 }
56 }
57 return 0;
58 }運行結果:


3.如果所有指向管道讀端的文件描述符都關閉了,這時有進程向管道的寫端write,那么該進程會收到信號SIGPIPE,通常會導致進程異常終止。
1 #include<stdio.h>
2 #include<sys/wait.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/types.h>
6 #include<stdlib.h>
7 int main()
8 {
9 int _pipefd[2]={-1,-1};
10 int ret=pipe(_pipefd);
11 if(ret==-1)
12 {
13 perror("pipe");
14 return 2;
15 }
16
17 pid_t id=fork();
18 if(id<0)
19 {
20 perror("fork");
21 return 2;
22 }
23 else if(id==0)
24 {
25 close(_pipefd[0]);
26 char buf[]="hello world";
27 int count=5;
28 while(count--)
29 {
30 write(_pipefd[1],buf,strlen(buf));
31 sleep(1);
32 }
33 close(_pipefd[0]);
34 }
35 else
36 {
37 close(_pipefd[1]);
38 char buf[1024]={0};
39 int i=5;
40 while(i--)
41 {
42 if(i==3)
43 {
44 close(_pipefd[0]);
45 }
46 memset(buf,'\0',sizeof(buf));
47 ssize_t _size=read(_pipefd[0],buf,sizeof(buf)-1);
48 if(_size>0)
49 {
50 buf[_size]='\0';
51 printf("buf:%s\n",buf);
52 }
53 }
54 int status=0;
55 pid_t _pid=waitpid(id,&status,0);
56 printf("waitpid: %d,return status:%d\n",id,status&0xff);
57 }
58 //printf("%d ,%d \n",_pipefd[0],_pipefd[1]);
59 return 0;
60 }運行結果:


4.如果有指向管道讀端的文件描述符沒關閉,持有管道讀端的進程也沒有從管道中讀數據,這時有進程向管道寫端寫數據,那么在管道被寫滿時再次write會阻塞,直到管道中有空位置了才寫入數據并返回。
1 #include<stdio.h>
2 #include<sys/wait.h>
3 #include<string.h>
4 #include<unistd.h>
5 #include<sys/types.h>
6 #include<stdlib.h>
7 int main()
8 {
9 int _pipefd[2]={-1,-1};
10 int ret=pipe(_pipefd);
11 if(ret==-1)
12 {
13 perror("pipe");
14 return 2;
15 }
16
17 pid_t id=fork();
18 if(id<0)
19 {
20 perror("fork");
21 return 2;
22 }
23 else if(id==0)
24 {
25 close(_pipefd[0]);
26 char buf[]="hello world";
27 int count=5;
28 while(count--)
29 {
30 write(_pipefd[1],buf,strlen(buf));
31 sleep(1);
32 }
33 close(_pipefd[0]);
34 }
35 else
36 {
37 close(_pipefd[1]);
38 int status=0;
39 pid_t wait=waitpid(id,&status,0);
40 if(wait==id)
41 printf("wait:%d,status:%d\n",wait,status);
42 }
43 return 0;
44 }總結匿名管道特點:
單向通信,適用于有血緣關系的進程通信。
管道提供流式服務(數據按序,不規定一次讀多少)
管道內部有保證數據讀完(完整性)。
進程間同步
通過路徑看到共同資源
在shell下交互的建立
調用函數
//client:
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<stdlib.h>
6 #include<string.h>
7 #include<fcntl.h>
8 int main()
9 {
10 umask(0);
11 int fd=mkfifo("./.tmp",S_IFIFO|0666);
12 if(fd<0)
13 {
14 perror("mkfifo");
15 exit(1);
16 }
17 int _fd=open("./.tmp",O_WRONLY);
18 if(_fd<0)
19 {
20 perror("mkfifo");
21 exit(1);
22 }
23 while(1)
24 {
25 char buf[1024];
26 fflush(stdout);
27 memset(buf,'\0',sizeof(buf));
28 printf("client:");
29 size_t size=read(0,buf,sizeof(buf)-1);
30 buf[size]='\0';
31 write(_fd,buf,strlen(buf));
32 }
33 return 0;
34 }
//server:
1 #include<stdio.h>
2 #include<string.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<fcntl.h>
6 #include<unistd.h>
7 #include<stdlib.h>
8 int main()
9 {
10 int _fd=open("./.tmp",O_RDONLY);
11 if(_fd<0)
12 {
13 perror("open");
14 exit(1);
15 }
16 char buf[1024];
17 while(1)
18 {
19 memset(buf,'\0',sizeof(buf));
20 ssize_t _size=read(_fd,buf,sizeof(buf)-1);
21 if(_size>0)
22 {
23 buf[_size]='\0';
24 printf("server:%s",buf);
25 }
26 else
27 {
28 printf("read error\n");
29 break;
30 }
31 }
32 close(_fd);
33 return 0;
34 }//Makefile編寫: .PHONY:all 2 all:client server 3 4 client:client.c 5 gcc -o $@ $^ 6 server:server.c 7 gcc -o $@ $^ 8 .PHONY:clean 9 clean: 10 rm -f client server .tmp
結果驗證:打開兩個終端,不同進程可以通信。

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。