Linux pipe 管道到底是什么? 跟踪mkfifo到内核
Thursday, 15. March 2007, 03:31:32
[By
Xalanz]技术问题往往都是这样,当它不出问题的时候,你并不会有特别的兴趣去究根问底,所以,出了问题,往往就是好事.Linux
的Pipe 出了一个问题,我不得不问自己,Pipe 到底是什么,在Linux kernel 里面是怎么实现的.
(1)第一步,你调用了mkfifo()或者使用mkfifo命令,在磁盘文件系统中建立了一个有名字的fifo
文件,但是mkfifo并不是一个系统调用,mkfifo()最终调用了mknod()系统调用来执行实际的功能。
(2)mknod()系统调用的内核部分是在linux\fs\namei.c
文件中sys_mknod()实现对系统调用的接口。
(2)对于fifo,sys_mknod()进一步调用虚拟文件系统的统一接口vfs_mknod()。
(3)而vfs_mknod()将调用相应目录的inode节点的mknod()方法来执行真正的mknod()操作。
1、Pipe 在那个子系统实现的? 在网络子系统、还是进程间通讯部分,还是什么?
Pipe 是在文件系统部分实现的。
2、Pipe 文件还是什么?
Pipe 是一种特殊的文件系统。
********************************************************************************************
mkfifo(建立实名管道)
相关函数
pipe,popen,open,umask
表头文件
#include
#include
定义函数
int
mkfifo(const char * pathname,mode_t mode);
函数说明
mkfifo()会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限(mode%~umask),因此
umask值也会影响到FIFO文件的权限。Mkfifo()建立的FIFO文件其他进程都可以用读写一般文件的方式存取。当使用open()来打开
FIFO文件时,O_NONBLOCK旗标会有影响
1、当使用O_NONBLOCK 旗标时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO
文件来读取,则写入的操作会返回ENXIO 错误代码。
2、没有使用O_NONBLOCK 旗标时,打开FIFO
来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO
文件来读取后才正常返回。
返回值
若成功则返回0,否则返回-1,错误原因存于errno中。
错误代码
EACCESS
参数pathname所指定的目录路径无可执行的权限
EEXIST
参数pathname所指定的文件已存在。
ENAMETOOLONG
参数pathname的路径名称太长。
ENOENT
参数pathname包含的目录不存在
ENOSPC
文件系统的剩余空间不足
ENOTDIR
参数pathname路径中的目录存在但却非真正的目录。
EROFS
参数pathname指定的文件存在于只读文件系统内。
示例1:
#include
#include
#include
#include
int main(void)
{
char
buf[80];
int
fd;
unlink(
"zieckey_fifo" );
mkfifo(
"zieckey_fifo", 0777 );
if ( fork()
> 0 )
{
char s[] =
"Hello!\n";
fd = open(
"zieckey_fifo", O_WRONLY );
write( fd,
s, sizeof(s) );
//close( fd
);
}
else
{
fd = open(
"zieckey_fifo", O_RDONLY );
read( fd,
buf, sizeof(buf) );
printf("The
message from the pipe is:%s\n", buf );
//close( fd
);
}
return
0;
}
执行
hello!
示例2: #include
#include
#include
#include
#include
int main( int argc, char **argv )
{
mode_t mode
= 0666;
if ( argc
!=2 )
{
printf(
"Usage:[%s] fifo_filename\n", argv[0] );
return
-1;
}
if (mkfifo(
argv[1], mode)<0 )
{
perror(
"mkfifo");
return
-1;
}
return
0;
}
***************************************************************************************
最近做的项目遇到一个问题:把播放器模块和UI模块整合成一个可执行程序,整合好后,一运行报出一个运行时错误,什么free一个地址出错了。这种问题是内存操作引起的,很难找出原因,而且这问题也不知道是UI模块还是播放器模块引起的,真是摸不着头脑。
后来想想,把播放器编译成一个单独的可执行程序,UI也是单独的可执行程序,然后两者之间通过管道来实现进程间的通信。我使用的是命名管道,其实命名管道的创建和使用也不算太难:
1、mkfifo创建一个管道,需要加一些创建标志,如O_CREAT等;
2、使用open函数来获取管道描述符,这个关键点也是设置标志,如O_NONBLOCK,O_RDONLY,
O_WRONLY等。
3、然后在一个进程中使用write进行写,在另外一个进程中使用read进行读。这样就构造了一个单双工的通道。可以再创建一个管道来进行反向通信,从而实现双向通信。
4、退出时使用unlink把管道文件删除掉。
大概的步骤就是这样,关键是根据需要创建合适的通讯模式。
注意:
我在open的时候使用了O_NONBLOCK |
WRONLY标志,然后出错了,返回-1。后来查看errno才知道,使用了O_NONBLOCK标志,必须先有进程以读的方式打开这个管道,才能以O_NONBLOCK
| WRONLY标志来打开这个管道。
***************************************************************************************
讲述了管道和有名管道的用法
原文链接: