管道
管道分为有名管道和无名管道,无名管道主要用于带亲缘关系间的进程之间的通信,有名管道可以用于任意两个进程之间的通信。
管道的通信方式:半双工的方式
可以看到创建管道的内核代码中有一个inode 节点,两个file 节点
struct inode 节点中记录了文件在存储介质上的位置以及分布的信息,即:一个inode对应一个物理上的具体的文件
struct file 是一个文件描述符。每一个进程的pcb 块中都有一个专门存放文件描述符的数组
struct dentry 节点中记录了一个文件的逻辑信息,该结构体中有一个指针i_inode可以指向一个struct inode 结构,可以有多个文件名不同的文件来指向同一个struct inode,即:多个struct dentry 中的i_inode指向同一个struct inode
int do_pipe(int *fd)
{
struct qstr this;
char name[32];
struct dentry *dentry;
struct inode * inode;
struct file *f1, *f2;
int error;
int i,j;
进程对每个已经打开的文件的操作都是通过file 数据结构进行的,只有在同一个进程按相同的模式打开一个文件时才能共享同一个数据结构。管道实际上是一个无形的文件,对这个文件的操作要通过两个已打开的文件进行,分别代表文件的两端,所以管道的两端不共享同一个file数据结构,所以要调用get_empty_file()为管道的两端各分配一个file数据结构。
同时,每个文件都是由一个inode结构代表的,虽然管道是一个无形的 文件,它也要有一个inode 结构,所以需要在创建临时管道的时候调用get_pipe_inode()创建一个inode 结构,inode 结构中有一个i_pipe指针,指向pipe_inode_info数据结构,只有inode所代表的文件是一个管道的时候才能用到该指针。
创建了inode结构后,调用pipe_new()分配所需要的缓冲区。再分配一个缓冲区作pipe_inode_info 数据结构
看一下分配的过程
//获取两个文件描述符
f1 = get_empty_filp();
if (!f1)
goto no_files;
f2 = get_empty_filp();
if (!f2)
goto close_f1;
/**
* get_pipe_inode为pipefs文件系统中的管道分配一个索引节点对象并对其进行初始化。
* 它会考虑一些资源限制,所以不一定能够分配成功。
*/
inode = get_pipe_inode();
if (!inode)
goto close_f12;
/**
* 为读和写分配文件对象和文件描述符。存放到i,j中
* 并将f1,f2设为只读和只写。
* 管道的两端只能有一端进行读另一端进行写
*/
error = get_unused_fd();
if (error < 0)
goto close_f12_inode;
i = error;
error = get_unused_fd();
if (error < 0)
goto close_f12_inode_i;
j = error;
error = <