Linux进程间通信---管道
IPC:
IPC,即Inter-Process Communication,进程间通信。是进程间通信的对象,包括管道、消息队列、信号量、套接字等。关于IPC结构,首先IPC结构是内核维护的,不属于某个特定进程。IPC结构由两个东西标识:标识符(ID)和键(key)。其中,ID是IPC的内部名字,只在进程间通信使用;key是IPC的外部名字,多个进程针对同一个key调用get函数时,会得到相同的ID,即标识了同一个IPC,进程间就可以通过这个共同的IPC进行通信。
无名管道:
无名管道只能用于两个具有公共祖先的进程之间,即:只能用于相关的两个进程通信,不能用于不相关的两个进程通信。常用实现函数是:int pipe(int fd[2])。pipe函数创建一个半双工管道。fd[0]用于进程读端,fd[1]用于进程写端,一个进程的fd[1]输出是另一个进程fd[0]的输入。实现例程如下:
#include<stdio.h> #include<stdlib.h> #include<sys/types.h> #include<unistd.h> int main() { int fd[2]; char line[MAX_LINE]; if(pipe(fd)<0); //建立管道,fd[1]写,fd[0]读。返回0表示成功,返回-1表示失败 err_sys("pipe erroe"); if((pid = fork()) < 0) //创建子进程 err_sys("fork error"); else if(pid > 0) //父进程 { close(fd[0]); //关闭父进程的读端 write(fd[1], "data", 4); //父进程向fd[1]描述符中写 } else //子进程 { close(fd[1]); //关闭子进程的写端 int n = read(fd[0], line, MAX_LINE); //子进程从fd[0]描述符中读 write(STDOUT_FIFENO, line, n); //将读到的内容写到标准输出(cout) } exit(0); }
使用无名管道的优缺点:优点:相对于建立一个磁盘文件,两个进程通过磁盘读写来进行通信的方法,使用无名管道不需要创建中间临时磁盘文件,提升了进程间通信的速度。缺点:无名管道只能在具有公共祖先的两个进程间使用,即两个进程只能是父子进程或有共同父进程的两个子进程。
有名管道(FIFO):
无名管道只能在两个相关的进程间使用(两个进程有公共祖先),但是通过FIFO,不相关的进程也能交换数据进行通信。常用的实现函数是mkfifo(path, mode),他创建一个FIFO,类似于创建一个文件,路径名path位于文件系统。FIFIO的使用类似于CS通信,write_fifo相当于客户端,向事先知道的管道发送消息;read_fifo相当于服务器端,创建一个众所周知的管道,监控管道的读端,当有数据到来时读出并处理。实现例程如下:
(1)read_fifo:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<sys/types.h> #include<sys/stat.h> int main() { int fd; int len; char buf[1024]; if(mkfifo("/tmp/fifo1", 0666) < 0) // 创建FIFO管道,权限为666或777 perror("Create FIFO Failed"); if((fd = open("fifo1", O_RDONLY)) < 0) // 以读打开FIFO { perror("Open FIFO Failed"); exit(1); } while((len = read(fd, buf, 1024)) > 0) // 读取FIFO管道 printf("Read message: %s", buf); close(fd); // 关闭FIFO文件 return 0; }
(2)write_fifo:
#include<stdio.h> #include<stdlib.h> // exit #include<fcntl.h> // O_WRONLY #include <unistd.h> #include<sys/types.h> #include<sys/stat.h> int main() { int fd; printf("I am %d process.\n", getpid()); // 说明进程ID if((fd = open("/tmp/fifo1", O_WRONLY)) < 0) // 以写打开一个FIFO { perror("Open FIFO Failed"); exit(1); } char buf[11] = "hello,fifo"; if(write(fd, buf, 11) < 0) // 写入到FIFO中 { perror("Write FIFO Failed"); close(fd); exit(1); } sleep(1); // 休眠1秒 close(fd); // 关闭FIFO文件 return 0; }