一、管道
1.定义:
管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。 本质上,管道也是一种文件,但却和一般的文件有不同。
(单向:数据只能从一个进程到另一个进程,一个写管道,一个读管道)
2.不足:
1)管道的缓冲区大小是受限制的(缓冲区固定)。在Linux中,该缓冲区大小为1页(4K字节)
2)管道所传输的是无格式的字节流。这就需要管道输入方和输出方事先约定好数据格式。
3.通信方式:
通过管道通信的两个进程,一个进程向管道写数据,另外一个从中读数据。写入的数据每次都添加到管道缓冲区的末尾,读数据的时候都是从缓冲区的头部读出数据的。
一次性操作:对于管道文件指向的内存中存储数据一旦被读,它就从管道中被抛弃,释放空间以便写入更多数据。
4.分类:
管道分为有名管道和无名管道。
5.管道结构:
在Linux中,管道的实现没有专门的数据结构,而是借助于文件系统的file结构和VFS的索引节点iNode,将两个file结构指向同一个临时的VFS索引节点,而VFS 索引节点又指向一个物理页面而实现。
二、有名管道(name pipe或者FIFO)
1.定义: 利用管道文件实现进程间通讯,管道文件仅仅是磁盘上的一个文件标识,其真实数据存储在内存上。
2.创建:1)命令:mkfifo filename 2)函数:int mkfifo();
4. 有名管道(name pipe或FIFO):FIFO不同与管道之处在与她提供一个路径名与之关联,以FIFO的文件形式存储在文件系统中。有名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信了。值得注意的是FIFO(First In First Out)总是按照先进先出的原则工作,第一个被写入的数据首先从管道中读出。
对于管道文件的打开操作,必须有读有写,否则open函数阻塞;
三、无名管道
1.定义:相对于有名管道,其并不存在管道文件。
2.限制:无名管道能完成进程间通讯,必须借助于父子进程共享fork之前打开的文件描述符,因此,无名管道只能应用于父子进程之间的通讯。
3.int pipe(int pipefd[2]):无名管道两端分别用描述符pipefd[0]及pipefd[1]来描述。需要注意的是,管道两端的任务是固定的,一端只能用于读,有描述符pipefd[0]表示,称其为管道读端;另一端只能用于写,由描述符pipe[1]来表示,称其为管道写端。
#include<stdio.h>
#include<unistd.h>
int main()
{
int n,fd[2];//fd[]文件描述符的数组,用于创建管道
pid_t pid;
char line[100];
if(pipie(fd)<0)//创建管道
{printf(“pipe create error\n”);}
if( pid=fork() )< 0 )//fork创建新进程
{printf(“fork error\n”);}
else if(pid>0)//父进程:关闭管道的读端,在写端写入
{
close(fd[0]);
write(fd[1],“hello\n”,5);
}
else
{
close (fd[1]);//子进程:关闭写端,读出数据
n=read(fd[0],line,100);
write(STDOUT_FILENO,line,n);
}
return 0;
}
四、read函数
read函数对于普通文件是非阻塞运行的,但是对于管道文件其是一种阻塞运行的。
read函数返回的条件:1)管道中有数据;2)所有的写端关闭。