进程间通信的常用方式,特征
管道:简单
信号:开销小
mmap映射:非血缘关系进程间
socket:稳定
管道:
实现原理:内核借助环形队列机制,使用内核缓冲区实现。
创建管道文件: mkfifo +文件
特质:
1.伪文件
2.管道中的数据只能一次。
3.数据在管道中,只能单向流动
局限性:
1.自己写,不能自己读。
2.数据不可以反复读。
3.半双工通信
4.血缘关系进程可用。
pipe函数:
创建,打开管道。
int pipe(int fd[2]);
参数:fd[0]:读端。
fd[1]; 写端。
返回值:成功:0
失败:-1 errno
管道的读写行为:
读管道:
1.管道有数据,read返回实际读到的字节数。
2.管道无数据:(1)无写端,read返回0(类似读到文件尾)
(2)有写端,read阻塞等待。
写管道:
1.无读端,异常终止。(SIGPIPE导致的)
2.有读端: (1)管道已满,阻塞等待。
(2)管道未满,返回写出的字节个数。
pipe管道:
父子进程间通信:
兄弟进程间通信:
fifo管道:
无血缘关系进程间通信:
void *mmap(void *addr,size_t length,int prot,int flags,int fd,off_t offset); 创建共享内存映射
参数:
addr:指定映射区的首地址。通常传NULL,表示让系统自动分配
length:共享内存映射区的大小。(<=文件的实际大小)
prot:共享内存映射区的读写属性。
PROT_READ、PROT_WRITE、PROT_READ|PROT_WRITE
flags:标注共享内存的共享属性。MAP_SHARED、MAP_PRIVATE.
fd:用于创建共享内存映射区的那个文件的文件描述符。
offset:默认0,表示映射文件全部。偏移位置。需要4k的整数倍。
返回值:
成功:映射区的首地址。
失败:MAP_FAILED,errno
代码案例:
1 #include<stdio.h>
2 #include<string.h>
3 #include<stdlib.h>
4 #include<fcntl.h>
5 #include<errno.h>
6 #include<sys/mman.h>
7 #include<unistd.h>
8 #include<pthread.h>
9 void sys_err(const char *str)
10 {
11 perror(str);
12 exit(1);
13 }
14
15 int main(int argc,char *argv[])
16 {
17 char *p=NULL;
18 int fd;
19
20 fd=open("testmap",O_RDWR|O_CREAT|O_TRUNC,0644);
21 if(fd==-1)
22 {
23 sys_err("open error");
24 }
25 /* lseek(fd,10,SEEK_END); //两个函数等价于ftruncate()函数
26 write(fd,"\0",1);
27 */
28 ftruncate(fd,10);
29 int len=lseek(fd,0,SEEK_END);
30 p=mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
31 if(p==MAP_FAILED){
32 sys_err("mmap error");
33 }
34 //使用p对文件进行读写操作。
35 strcpy(p,"hello mmap"); //写操作
36 printf("-----%s\n",p);
37
38 int ret=munmap(p,len);
39 if(ret==-1){
40 sys_err("munmap error");
41 }
42 return 0;
43 }