上文在将进程间通信的管道时遗漏了FIFO,现将其补上。
三、有名管道(FIFO)
有名管道(FIFO)是相对于无名管道(PIPE),两者都为管道,但是却有不同。
1.特点
- FIFO可用于无血缘关系进程间的通信,突破的PIPE只能在有血缘关系之间通信的局限。
- 它是在文件系统中存在的一个伪文件,不会占用磁盘空间。只是在内核中开辟一段内存空间,以供数据传输。
- 当利用fifo管道进行通信时。管道读写可出现阻塞于非阻塞两种状态。
当open时在没有指明使用非阻塞(O_NONBLOCK)的标志时,只读的的文件描述符号会阻塞等待另一个为写的进程,同理只写的也会阻塞等待另一个为读的进程。
当指明非阻塞标志时,读的进程会立即返回,如果没有一个进程为了写而打开该fifo时,返回错误,其errno是ENXIO。同样写的进程也会立即返回,如果没有一个进程为读而打开该fifo时,会返回一个信号,该信号为SIGPIPE。如果一个为写的进程关闭该fifo是,它会为读的进程产生一个文件结束符号(EOF)。
2.函数原型
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename,mode_t mode);
此函数可以在代码中创建管道文件,并可通过读写该文件完成进程间通讯。
3.示例代码
在利用FIFO进行进程间通信时,可以事先利用mkfifi命令创建好一个管道文件,然后利用文件的读写操作进行进程间通信。
mkfifo fifotestfile
可以在终端看到相应创建的管道文件
prw-rw-r-- 1 fengl fengl 0 7月 8 17:59 fifotestfile
可以看见这个文件的类型是个管道文件(p),这个文件可以正常读写,我们可以在终端输入cat < fifotestfile,在另外一个终端echo "hello" > fifotestfile,便可进行简单的数据通信测试,这里不在细说,可自行测试。
下面通过示例代码创建管道并完成进程间通信。
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int ret;
char buff[256];
int fd;
memset(buff, 0, sizeof(buff));
unlink("fifotest");
ret = mkfifo("fifotest", 0777);
if (ret == -1){
perror("mkfifo failed\n");
return -1;
}
fd = open("fifotest", O_RDONLY);
if (fd == -1) {
perror("open fifotest failed\n");
return -1;
}
while (1) {
read(fd, buff, 256);
printf("read : %s\n",buff);
}
close(fd);
return 0;
}
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[])
{
int ret;
char buff[] = {"hello my brother"};
int fd;
fd = open("fifotest", O_WRONLY);
if (fd == -1) {
perror("open fifotest failed\n");
return -1;
}
while (1) {
write(fd, buff, strlen(buff));
sleep(1);
}
close(fd);
return 0;
}
~
运行结果如下:
read : hello my brother
read : hello my brother