管道:
管道是Unix中最古老的进程间通信的形式;
我们把从一个进程连接到另一个进程的一个数据流称为一个“管道”;
匿名管道:
#include<unistd.h>
功能:
创建一个无名管道
原型:
int pipe(int fd[2]);
参数:
fd:文件描述符数组,fd[0]表示读端,fd[1]表示写端
返回值:
成功返回0,失败返回错误代码;
代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd,h>
int main()
{
int fds[2];
char buf[100];
int len;
if (pipe(fds) == -1)
perror("make pipe"), exit(1);
while (fgets(buf, 100, len) != len)
{
len = strlen(buf);
if (write(fds[1], buf, len) != len)
{
perror("write to pipe");
break;
}
memset(buf, 0x00, sizeof(buf));
if ((len = read(fds[0], buf, 100)) == -1)
{
perror("read form pipe");
break;
}
if (write(1, buf, len) != len)
{
perror("write to stdout");
break;
}
}
}
管道的特点:
只能用于具有共同祖先的进程之间的通信,通常一个管道由一个进程创建,然后该进程调用fork,此后父子进程之间就可以应用该管道;
管道提供流式服务;
进程退出,管带释放所以管道的生命周期随进程;
内核会对管道操作进行同步与互斥;
管道是半双工,数据只能向一个方向流动,需要双方通信时,需建立两个管道;
命名管道:
命名管道时一种特殊的类型文件;
管道应用的一个限制就是只能在具有共同祖先的进程间通信;
如果我们想在不相关的进程间交换数据,可以使用FIFO文件来做这项工作,他就是命名管道;
如何创建一个命名管道:
命名管道可以从命令行上创建
$ mkfifo filename
命名管道也可以从程序里创建
int mkfifo(const char* filename,mode_t mode);
创建命名管道:
int main(int argc,char *argv[])
{
mkfifo("p2",0644);
return 0;
}
命名管道的打开规则:
如果当前打开操作是为读而打开FIFO时:
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO;
O_NONBLOCK enable:立刻返回成功;
如果当前打开操作为写而打开FIFO时:
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO;
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO;
匿名管道和命名管道的区别:
匿名管道由pipe函数创建并打开;
命名管道由mkfifo函数创建,由open打开;
FIFO与pipe之间唯一的区别在他们创建与打开方式不同,一旦这些工作完成之后,他们具有相同的语义;