由于无名管道的缺点,从而产生有有名管道(管道=队列):在系统中存在这样一个文件节点。
作用:实现非父子或有亲缘关系的进程之间的通信。
【注】只有文件节点不占磁盘空间的有:有名管道,字符设备,块设备,套接字。
例子1:有名管道的创建,调用mkfifo()函数。
#include"stdio.h"
#include"unistd.h"
#include"stdlib.h"
int main()
{
int ret;
ret = mkfifo("./mkfifo",0777);
if(ret<0)
{
printf("create mkfifo failure\n");
return -1;
}
printf("create mkfifo success\n");
return 0;
}
图成功创建有名管道mkfifo文件,其权限于umask有关系。
【注】mkfifo并不是生成于内核里,而是用户空间里的节点,当进程调用open函数打开mkfifo文件时,才会在内核空间生成一个管道缓存。
例子2:基于例子1,通过有名管道实现两个无亲缘关系的进程之间的通信。建立两个进程process_1.c, process_2.c;分别打印5次first和second,第一个进程先打印,第二个进程后打印。即当第一个进程打印完后通过有名管道告诉第二个进行,然后第二个进程开始打印。
1)由于mkfifo已经创建好,进程process_1利用open()函数打开mkfifo,打印5条语句之后。向管道写入'1',代表process_2可以打印了;
process_1.c文件:
`
#include"stdio.h"
#include"unistd.h"
#include"fcntl.h"
#include"stdlib.h"
int main()
{
int fd;
int process_inter=0;
fd = open("./mkfifo",O_WRONLY);//打开生成的mkfifo文件后,在内核生成有名管道
if(fd<0)
{
printf("open mkfifo failure\n");
return -1;
}
printf("open mkfifo success\n");
int i;
for(i=0;i<5;i++)//打印5次
{
printf("first\n");
}
sleep(5);//睡眠5秒
process_inter = 1;//信号制为1
write(fd,&process_inter,1);//1写入有名管道
close(fd);//关闭管道
while(1);//进入死循环,确保进程不会结束
return 0;
}
进程process_2.c的内容:
#include"stdio.h"
#include"unistd.h"
#include"fcntl.h"
#include"stdlib.h"
int main()
{
int fd;
int process_inter=0;
fd = open("./mkfifo",O_RDONLY);//打开管道
if(fd<0)
{
printf("open mkfifo failure\n");
return -1;
}
printf("open mkfifo success\n");
read(fd,&process_inter,1);//读取管道中进程process_1的信息,即刚才进程process_1写进管道的1
while(process_inter==0);//若是读取不到刚才进程process_1写进管道的1,则进入死循环,不执行以下语句
int i;
for(i=0;i<5;i++)
{
printf("first\n");
}
close(fd);//关闭通道
while(1); //确保进程不会先结束
return 0;
}
编译进程,并打开两个窗口,先运行process_1,后运行process_2,运行结果输出如图;
process_1运行打印first后,睡眠5秒后,制process_inter=1;此时,process_2读取信号1,并打印输出;
以上例子与讲解,说明了有名管道可实现非亲缘关系进程间的通信。