1 有名管道
有名管道与无名管道的通信机制差不多,唯一不同在于,有名管道需要在文件系统中创建指定名称的管道文件,用于通信。
一旦创建好一个有名管道文件,任何进程都可以打开该文件,并进行读写操作。因此有名管道可以用在无父子关系的进程间通信。
2 接口
2.1 创建
Linux下使用mkfifo接口来创建管道文件,接口原型如下。
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
- pathame: 要创建的管道文件名
- mode: 指定文件的读写权限
- 返回值:成功返回0,失败返回-1
2.2 打开、关闭及读写操作
有名管道的打开、关闭及读写操作与普通文件,采用open、close、write、read等系统文件操作接口来操作管道。
在操作有名称管道时,需要注意:
- 打开管道的读写模式要么只读,要么只写,不可同时在一个文件描述符上设置可读写模式,这样也就失去管道的意义了
- 阻塞问题:如果打开选项设置
O_NONBLOCK
参数,则表示打开操作为非阻塞,如果不带该参数,则表示打开操作是阻塞的。
具体有以下两种情况
(1)对于以只读方式(O_RDONLY)打开有名管道
,如果调用open
是阻塞的,那么除非有一个进程以写方式打开同一个有名管道
,否则一直阻塞在open
调用中;如果open
是非阻塞的,则open
调用后会立即返回。
(2)对于以只写方式(O_WRONLY)打开有名管道
,如果调用open
是阻塞的,那么除非有一个进程以只读方式打开同一个有名管道
;否则将一直阻塞在open
调用中;如果open
是非阻塞的,则open
调用后会立即返回,但如果没有其他进程以只读方式打开同一个有名管道
,open
调用将返回-1,并且有名管道
也不会被打开。
3 示例
3.1 发送程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (mkfifo("/tmp/fifo", 0666) < 0) {
printf("make fifo failed\n");
return -1;
}
int fd = ::open("/tmp/fifo", O_WRONLY);
if (fd < 0) {
printf("Open fifo file failed\n");
return -1;
}
::write(fd, "Hello", 6);
::close(fd);
return 0;
}
3.2 接收程序
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int fd = ::open("/tmp/fifo", O_RDONLY);
if (fd < 0 ) {
printf("%s(%s[%d]): watcher init failed", __FILE__, __func__, __LINE__);
return;
}
char msg[6];
::read(fd, msg, 6);
printf("receive message: %s\n", msg);
return 0;
}