Linux-进程间通信(一、匿名管道与命名管道)
2017-12-20 15:26
495 查看
LINUX进程间通信(二、消息队列)
匿名管道:
头文件:#include<unistd.h> 函数原型:int pipe(int fd[2]); 返回值:成功返回0,失败返回错误代码 注:fd:文件描述符数组,fd[0]代表读端,fd[1]代表写端
用法:
单个进程中的管道几乎没有任何用处,通常,调用pipe的进程接着调用fork,从而创建了一个父进程与子进程之间的[b]半双工的IPC通道。在当前进程假如进行读操作时,就可关闭写端(fd[1])如图:[/b][b]示例:假设现有一对父子进程,子进程需要读取屏幕上输入的信息,再通过管道将信息传给父进程,父进程再将该信息打印到屏幕上。[/b]
分析:
①先要清楚哪些资源是父子进程必须共有的,在fork之前就得定义,在此例子中就是匿名管道pipe;
②如果当前进程是父进程时:由于要做的是从管道读取数据,那么就关闭写端;读取完成后将数据打印到屏幕上;
③如果当前进程是子进程:关闭读端;将stdin的信息读取并写入到管道中,等待父进程读取。
实现如下:
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> #include <string.h> int main() { //creat pipe int fd[2] = {0}; if(pipe(fd) == -1){ perror("pipe"); exit(1); } //pipe create 4000 success int res = fork(); if(res > 0){ //father close(fd[1]); char buf[1024] = {0}; ssize_t tmp = read(fd[0],buf,sizeof(buf)-1); if(tmp == -1){ perror("read"); exit(1); }else if(tmp == 0){ printf("read done\n"); exit(0); }else{ printf("father read : %s",buf); } }else if(res == 0){ //child close(fd[0]); char tmp[256] = {0}; printf("child say : "); fflush(stdout); read(0,tmp,sizeof(tmp)-1); if(write(fd[1],tmp,strlen(tmp)) == -1){ perror("write"); exit(1); } //子进程正常退出 close(fd[1]); exit(0); }else{ perror("fork"); exit(1); } return 0; }
运行结果:
管道特点:
1、只能用于有亲缘关系的进程之间的通信;2、管道生命周期随进程;进程退出管道释放;
3、管道拥有同步与互斥机制;
4、具有半双工的特点;(要想实现双向通信,可建立两个管道)
管道读写规则
1、当管道中没有数据可读时:若pipe采取的是不阻塞方法,则直接read返回-1;采取是阻塞时,进程阻塞直到等待数据可以读;2、当管道满时:采用不阻塞方式将调用返回-1;反之write阻塞,直到有程序读走数据。
注:若想修改是否阻塞选项,需使用pipe2函数。具体用法自行man一下。int pipe2(int pipefd[2], int flags);
命名管道(FIFO):相当于创建一个文件,通过一个进程读 一个写来完成通信
[b]使用方法:FIFO创建成功后,一般的文件I/O函数(close,read,write,unlink等)都可用于FIFO。[/b]//使用mkfifo命令创建一个名为filaname的命名管道。 mkfifo filename //使用函数创建 函数原型:int mkfifo(const char* filename, mode_t mode); 参数:filename为所要创建的文件名,mode为文件权限. 返回值:成功返回0,失败返回-1
[b]注:FIFO是一种文件类型(p)[/b]
匿名管道与命名管道的区别:
1、匿名管道必须适用于有亲缘关系的进程之间;命名管道没有要求;2、匿名管道通过fd[0],fd[1]进行读写;命名管道通过特殊的FIFO文件进行读写。
[b]示例:client——server进程使用FIFO进行通信。[/b]
首先由服务器端先执行,创建FIFO文件,然后read阻塞等待有人向文件中写入数据,一旦client执行并写入数据,便开始进行“通信”。(由于是半双工,便只模拟实现了从client向server端发送数据)
server.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> int main() { if( mkfifo("myfifo",0666) == -1){ perror("mkfifo"); exit(1); } //FIFO creat success char buf[1024] = {0}; int rfd = open("myfifo",O_RDONLY); while(1){ printf("please wait...\n"); if(rfd > 0){ //open myfifo success printf("client say : "); fflush(stdout); ssize_t count = read(rfd,buf,sizeof(buf)-1); if(count > 0){ buf[count] = 0; printf("%s",buf); }else if(count == 0){ printf("client close\n"); exit(0); }else{ perror("read"); exit(1); } }else{ //open return -1,open failed perror("open"); exit(1); } } close(rfd); return 0; }
client.c
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <stdlib.h> #include <string.h> int main() { int wfd = open("myfifo",O_WRONLY); if(wfd == -1){ perror("open"); exit(1); } //open success char buf[1024] = {0}; while(1){ printf("client send : "); fflush(stdout); ssize_t count = read(0,buf,sizeof(buf)-1); if(count > 0){ buf[count] = 0; write(wfd,buf,strlen(buf)); }else{ perror("read"); exit(1); } } close(wfd); return 0; }
Makefile
.PHONY:all all : server client server:server.c gcc $^ -o $@ client:client.c gcc $^ -o $@ .PYHONY : clean clean: rm server client myfifo
运行结果显示:
注:1、一定要先运行server,否则没有创建myfifo文件,client将会打开失败,直接报错终止。
2、当同时运行多个client,一个server时,server将会全部接受client写入的信息;
3、当运行多个server,多个client时,此时一个client写入数据,随机只有一个server进程读取到信息。(同步互斥的体现)
相关文章推荐
- Linux--进程间通信之匿名管道及命名管道
- linux进程间通信:匿名管道和命名管道
- Linux进程间通信-匿名管道和与命名管道
- 【Linux】进程间通信(IPC)之匿名管道和命名管道以及测试用例
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信——使用匿名管道
- Linux进程间通信——使用命名管道
- 【Linux】进程间通信-命名管道FIFO
- Linux进程间通信(四):命名管道 mkfifo()、open()、read()、close()
- Linux进程间通信--无名管道和命名管道
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信——使用命名管道
- Linux进程间通信—无名管道和命名管道
- Linux进程间通信--匿名管道
- linux进程间通信----之使用匿名管道
- linux进程间通信方式之匿名管道http://blog.csdn.net/guoyang1007/article/details/4720984
- Linux进程间通信——使用匿名管道
- Linux进程间通信--使用命名管道
- linux中使用匿名管道实现进程间通信
- 【linux开发】进程间通信命名管道-共享内存-内存映射-消息队列-信号量