作者:小 琛
欢迎转载,请标明出处
每一个进程都是拥有自己独立的虚拟地址空间和页表结构,促使了进程独立,这也导致了进程之间合作存在问题,为了解决该问题,产生了进程间的通信。
管道
管道的本质:管道其实是内核当中的一块内存,相当于为进程通信而创建的缓冲区。
- 无名管道
- 有名管道
无名管道
- 无名管道的特性:
1、用于具有亲缘关系的进程
2、半双工,即数据流向唯一,只能从写端到读端
3、提供字节服务,即读和写都仅仅有两种状态:成功和失败,不会出现读一半或写一半
4、当读端读取后,数据就直接被拿走,不再存在于管道中
5、生命周期伴随进程
当读端不读,写端一直在写,管道写满的时候,写端就进行阻塞。
当写端不屑,读端一直在读,管道为空的时候,读端就进行阻塞
- 创建无名管道的函数
int pipe(int fd[2]); 成功返回0,失败返回-1
fd[2]数组是一个出参,意味着我们在使用的时候要定义一个数组。该数组返回创建管道的读端、写端自身的文件描述符。
fd[0]为读端,fd[1]为写端
- 测试管道的大小:
//测试管道的大小
17 void test2()
18 {
19 int fd[2];
20 int ret = pipe(fd);
21 if (ret < 0)
22 {
23 perror ("pipe");
24 }
25 int count=0;
26 while (1)
27 {
28 int writesize=0;
29 writesize=write(fd[1],"1",1);
30 if (writesize < 0)
31 break;
32 printf("[%d]\n",count++);
33 }
34
35 }
结果:
也就是说,共65535个字节,即64个字节
- 无名管道应用简单例子
39 void test3()
40 {
41 int fd[2];
42 int ret=pipe(fd);
43 if (ret < 0)
44 perror("pipe");
45 int temp=fork();
46 if (temp < 0)
47 perror("fork");
48 if (temp == 0)
49 {
50 write(fd[1],"hello",5);
51 //child
52 }
53 else
54 {
55 //father
56 wait(NULL);
57 char arr[10];
58 read(fd[0],arr,5);
59 printf("I read %s\n",arr);
60 }
61 }
有名管道
无名管道应用的一个最大限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,则无法支持。有名管道由此产生。
- 有名管道的创建
int mkfifo(const char *filename,mode_t mode);
filename:创建管道文件的名称 mode:权限
1 #include "stdio.h"
2 #include "unistd.h"
3 #include "sys/types.h"
4 #include "sys/wait.h"
5 #include "sys/stat.h"
6
7 int main()
8 {
9 int ret=mkfifo("myfifo",0664);
10 if (ret < 0)
11 perror("mkfifo");
12 return 0;
13 }
2. 借助有名管道实现两个终端的通信
创建一个server.c和一个client.c。利用有名管道,实现两个终端的通信。
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define ERR_EXIT(m) \
do{\
perror(m);\
exit(EXIT_FAILURE);\
}while(0)
int main()
{
int wfd = open("mypipe", O_WRONLY);
if(wfd < 0){
ERR_EXIT("open");
}
char buf[1024];
while(1){
buf[0] = 0;
printf("Please Enter# ");
fflush(stdout);
ssize_t s = read(0, buf, sizeof(buf)-1);
if(s > 0 ){
buf[s] = 0;
write(wfd, buf, strlen(buf));
}else if(s <= 0){
ERR_EXIT("read");
}
}
close(wfd);
return 0; }
server.c
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <unistd.h>
6 #include <stdlib.h>
7 #define ERR_EXIT(m) \
8 do{\
9 perror(m);\
10 exit(EXIT_FAILURE);\
11 }while(0)
12 int main()
13 {
14 umask(0);
15 if(mkfifo("mypipe", 0644) < 0){
16 ERR_EXIT("mkfifo");
17
18 }
19 int rfd = open("mypipe", O_RDONLY);
20 if(rfd < 0)
21 {
22 ERR_EXIT("open");
23 }
24 char buf[1024];
25 while(1)
26 {
27 buf[0] = 0;
28 printf("Please wait...\n");
29 ssize_t s = read(rfd, buf, sizeof(buf)-1);
30 if(s > 0 )
31 {
32 buf[s-1] = 0;
33 printf("client say# %s\n", buf);
34 }
35 else if(s == 0)
36 {
37 printf("client quit, exit now!\n");
38 exit(EXIT_SUCCESS);
39 }
40 else
41 {
42 ERR_EXIT("read");
43
44 }
45 }
46 close(rfd);
47 return 0;
48 }