linux进程间管道通信pipe与fifo
2017-09-13 20:47
639 查看
进程间通信的方式有很多种,管道通信就是其中一种,所谓管道通信就是通信流程类似管道流水具有单向性,数据只能从一个方向流向另一个方向。不能反向传输。
管道通信又分为无名管道通信、有名管道通信。无名管道只能用于父子进程间通信、自身通信(不常用意义不大),相互独立的进程不能通信,无名管道通信示意如下:
实际管道1、2的角色是由内核充当的。
pipe函数格式如下
函数的参数:数量为2的整形数组
规定无名管道通信 fd[1]数据写入端 fd[0]数据读取端
举例说明无名管道的用法,其实很简单:
结果表明如果管道为空,读取管道的进程将会阻塞,不再继续执行直到数据的来临。(可以通过运行./test 不向函数传入参数实验,程序将卡死)。
那么有读取空管道而进程不阻塞的办法么?其实是有的在linux发布的2.6.xx版本之后就加入了pipe2()函数,与pipe不同的是,pipe2函数加入了第二个参数,参数填写O_NOBLOCK之后,进程在读取空管道或写入非空管道时将不会阻塞进程。这里不在演示。
下面介绍有名管道fifo,fifo的优势在于它可以在不同进程间通讯,实质上fifo是一种特殊的文件,fifo一旦创建就可以用open函数打开它,一般的文件操作函数(close、write、read)都可以用于fifo,相关进程通过访问该文件,通过读取或写入相应数据达到进程间通讯的目的。
创建有名管道的函数结构如下:
当管道创建失败返回值小于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);
}
编译两个例程:
[root@localhost fifo]# gcc -o fifo1 fiforead.c
[root@localhost fifo]# gcc -o fifo2 fifowrite.c
[root@localhost fifo]# ls
fifo1 fifo2 fiforead.c fifowrite.c
[root@localhost fifo]# ./fifo1
等待读取管道数据
文件描述符:3
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:123456789
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:在另外一个终端执行
[root@localhost fifo]# ./fifo2
在文件目录可以查看一下文件情况
[root@localhost fifo]# ls
fifo1 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
管道通信又分为无名管道通信、有名管道通信。无名管道只能用于父子进程间通信、自身通信(不常用意义不大),相互独立的进程不能通信,无名管道通信示意如下:
实际管道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]# ls test test.c [root@localhost pipe]# ./test 123456 this is father process!! this is 3199 child process wait data now!! wait child exit read string is 123456 child 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]# ls
fifo1 fifo2 fiforead.c fifowrite.c
[root@localhost fifo]# ./fifo1
等待读取管道数据
文件描述符:3
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:123456789
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:
读出管道数据为:在另外一个终端执行
[root@localhost fifo]# ./fifo2
在文件目录可以查看一下文件情况
[root@localhost fifo]# ls
fifo1 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进程通信:命名管道FIFO小结
- 进程通信 [ fork() 管道( pipe() ) FIFO ]
- Linux C程序练习(3)进程通信之pipe、fifo、消息队列
- 服务器serverbuffergcc数据结构Linux进程通信:命名管道FIFO小结
- 【Linux进程通信】管道,FIFO
- linux 命名管道fifo实现进程间小数据通信
- 命名管道(FIFO) Linux进程进程间的通信之命名管道(FIFO)
- linux下进程间的通信——有名管道fifo学习笔记
- linux进程通信----FIFO(有名管道)
- 进程间的通信—管道pipe和fifo
- Linux进程通信:命名管道FIFO小结
- Linux进程通信-管道(pipe)
- Linux进程通信:命名管道FIFO小结
- Linux进程间的通信——有名管道fifo与守护进程deamon
- linux进程通信:管道(pipe)
- linux进程通信--管道(pipe)(含实例代码)
- linux进程通信--有名管道(FIFO)(含实例代码)
- Linux进程通信之管道和FIFO
- Linux 下父进程与子进程的通信(pipe管道)
- Linux进程通信之管道和FIFO