linux进程间管道通信pipe与fifo
来源:互联网 发布:51单片机项目外包网 编辑:程序博客网 时间:2024/05/21 13:26
进程间通信的方式有很多种,管道通信就是其中一种,所谓管道通信就是通信流程类似管道流水具有单向性,数据只能从一个方向流向另一个方向。不能反向传输。
管道通信又分为无名管道通信、有名管道通信。无名管道只能用于父子进程间通信、自身通信(不常用意义不大),相互独立的进程不能通信,无名管道通信示意如下:
实际管道1、2的角色是由内核充当的。
pipe函数格式如下
#include <unistd.h>int pipe(int pipefd[2]);
函数返回值:管道创建成功返回0 失败返回 -1函数的参数:数量为2的整形数组
规定无名管道通信 fd[1]数据写入端 fd[0]数据读取端
举例说明无名管道的用法,其实很简单:
#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/wait.h>#include <stdlib.h>int main(int argc,char *argv[]){ int fd[2]; //定义管道数组 pid_t pid,pd; //定义进程ID char buffer[100]; //定义管道数据缓冲区 if(pipe(fd)<0) printf("creat pipe failed!!\r\n"); //管道创建失败 pid=fork(); //创建子进程 if(pid<0) { printf("creat fork failed"); //创建进程失败 }else if(pid==0) { close(fd[1]); //子进程 关闭fd[1] 只用于接收数据 printf("this is %d child process wait data now!!\r\n",getpid()); //打印子进程进程号 显示等待数据 read(fd[0],buffer,50); //管道读取数据存放在buffer中 printf("read string is %s\r\n",buffer); //打印读取的数据 close(fd[0]); //关闭fd[0] }else if(pid>0) { close(fd[0]); //父进程关闭fd[0] 用于穿送数据 printf("this is father process!!\r\n"); //打印身份标识 这是父进程 sleep(5); //睡眠5秒钟 观察子进程状态 write(fd[1],argv[1],10); //向管道写入数据 数据为传入的第二个参数 printf("wait child exit\r\n"); //等待子进程退出 pd= wait(NULL); printf("child process %d is exit\r\n",pd); //子进程退出 打印子进程进程号 close(fd[1]); //关闭管道写入口 } exit(0); //进程结束}
执行以上代码结果:[root@localhost pipe]# gcc -o test test.c [root@localhost pipe]# lstest test.c[root@localhost pipe]# ./test 123456this is father process!!this is 3199 child process wait data now!!wait child exitread string is 123456child process 3199 is exit
可以看出父进程先执行,随后进入休眠状态,子进程开始执行。等待管道数据,父进程苏醒以后,向管道写入数据,随后等待子进程结束,子进程读取管道信息打印出来之后,结束进程。父进程收到子进程结束的消息。父进程打印结束的子进程进程号,结束自身。程序运行结束。结果表明如果管道为空,读取管道的进程将会阻塞,不再继续执行直到数据的来临。(可以通过运行./test 不向函数传入参数实验,程序将卡死)。
那么有读取空管道而进程不阻塞的办法么?其实是有的在linux发布的2.6.xx版本之后就加入了pipe2()函数,与pipe不同的是,pipe2函数加入了第二个参数,参数填写O_NOBLOCK之后,进程在读取空管道或写入非空管道时将不会阻塞进程。这里不在演示。
下面介绍有名管道fifo,fifo的优势在于它可以在不同进程间通讯,实质上fifo是一种特殊的文件,fifo一旦创建就可以用open函数打开它,一般的文件操作函数(close、write、read)都可以用于fifo,相关进程通过访问该文件,通过读取或写入相应数据达到进程间通讯的目的。
创建有名管道的函数结构如下:
#include <sys/types.h>#include <sys/stat.h>int mkfifo(const char *pathname,,mode_t mode);
当管道创建失败返回值小于0。
参数一是所创建fifo的名称可以跟路径。参数二是fifo的参数:其中最重要的是 0_CREAT 和O_EXCL这两个参数,这两个参数同时使用,O_CREAT创建fifo,O_EXCL创建管道失败返回错误。
同无名管道一样,访问有名管道无法满足进程要求时,进程将会阻塞,如试图读取空的fifo。如果想避免这种状况在打开fifo加入O_NONBLOCK这个参数即可,当访问无法满足要求时,进程不阻塞,但立刻出错返回,errno是ENXIO。
下面写两个例程说明一下fifo的用法。为什么是两个?因为fifo可以用于不同进程。所以这里利用两个例程来说明。
例程1:创建并读取fifo 打开fifo时加入O_NONBLOCK即使读取空fifo进程不会阻塞。
#include <stdio.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/types.h>#include <stdlib.h>#include <string.h>#define MYFIFO "/zhangchao/fifo/fifotest" //定义管道路径 名称int main(void){ int fd; //定义文件描述符 char buf[100]; //读取数据缓存区 if(mkfifo(MYFIFO,O_CREAT | O_EXCL)<0) //创建fifo管道 如果没有就创建 创建失败返回错误 { printf("创建FIFO失败\r\n"); return 0; } printf("等待读取管道数据\r\n"); fd=open(MYFIFO,O_RDONLY | O_NONBLOCK);//打开fifo管道 只读打开 没有数据不等待不会导致进程阻塞 printf("文件描述符:%d\r\n",fd); while(1) { memset(buf,0,sizeof(buf)); //清空缓存区 if(read(fd,buf,100)<0) //没有数据 printf("管道没有数据\r\n"); printf("读出管道数据为:%s\r\n",buf); sleep(1);}
close(fd);return 0; }例程2:写fifo
#include <stdio.h>#include <stdlib.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#define MYFIFO "/zhangchao/fifo/fifotest"int main(void){ int fd; char buf[]="123456789";fd=open(MYFIFO,O_WRONLY|O_NONBLOCK);if(write(fd,buf,100)<0) { printf("管道有数据没有被读走\r\n"); } close(fd); return 0;}
编译两个例程:[root@localhost fifo]# gcc -o fifo1 fiforead.c [root@localhost fifo]# gcc -o fifo2 fifowrite.c [root@localhost fifo]# lsfifo1 fifo2 fiforead.c fifowrite.c[root@localhost fifo]# ./fifo1等待读取管道数据文件描述符:3读出管道数据为:读出管道数据为:读出管道数据为:读出管道数据为:读出管道数据为:读出管道数据为:读出管道数据为:123456789读出管道数据为:读出管道数据为:读出管道数据为:读出管道数据为:读出管道数据为:在另外一个终端执行[root@localhost fifo]# ./fifo2
在文件目录可以查看一下文件情况
[root@localhost fifo]# lsfifo1 fifo2 fiforead.c fifotest fifowrite.c[root@localhost fifo]# ls -l fifotest p-wx------. 1 root root 0 9月 15 22:32 fifotest程序运行之后在文件目录多了 fifotest 文件,查看它的属性属于以p开头的管道文件,更加可以说明fifo有名管道其实就是一种特殊的文件。如果使用命令行界面,切换终端的方式为ctrl+alt+F(1~6);
代码运行平台CentOS6.3
- linux进程间通信之管道(pipe与fifo)
- 【Linux】进程间通信之管道pipe与FIFO
- linux进程间管道通信pipe与fifo
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信之管道(pipe)、命名管道(FIFO)与信号(Signal)
- Linux进程间通信——管道(pipe)与命名管道(FIFO)
- LINUX进程间通信:PIPE与FIFO
- LINUX进程间通信:PIPE与FIFO
- Linux进程间通信(一)之无名管道(PIPE)和有名管道(FIFO)
- 进程间通信(一): 管道(pipe+fifo)
- 进程间通信---------有名管道(named pipe/FIFO)
- 进程间的通信—管道pipe和fifo
- 进程通信 [ fork() 管道( pipe() ) FIFO ]
- Linux进程间通信-FIFO管道
- iOS 8苹方体使用说明
- POJ3280 Cheapest Palindrome (区间dp)
- Binary_Code 2-SAT神题
- 欢迎使用CSDN-markdown编辑器
- String、Stringbuffer、Stringbuilder的区别
- linux进程间管道通信pipe与fifo
- web前端打印需要注意的CSS样式
- 使用ping时,所用到的协议
- win7 快捷图标显示异常
- 【bzoj2242】[SDOI2011]计算器(ksm+扩欧+bsgs)
- 问题收集录
- 9.13第一轮扫荡战果
- Eclipse中新建java类自动生成作者和时间设置
- 最短路-SPFA 模板