前面所说的pipe我们叫它匿名管道,他只能用于有关系的进程之间的通信,为了实现不同进程之间的通信,有一种管道叫做命名管道Fifo来实现任意两个进程之间的通信。命名管道是一个设备文件,总是按照先进先出的工作方式来进行的,在文件系统中是以文件名的形式存在的。
首先创建命名管道可以有2种方式:
1.在shell下用命令mknod或者mkfifo来创建
2.调用系统函数mknod或者mkfifo函数创建
#include <sys/types.h>
#include <sys/stat.h>
int mknod(const char *path,mode_t mod,dev_t dev);
int mkfifo(const char *path,mode_t mode)
path为创建的命名管道的全路径名。
看下面代码:
umask(0);
if (mkfifo("/tmp/fifo",S_IFIFO|0666) == -1)
{
perror("mkfifo error!");
exit(1);
}
其中“S_IFIFO|0666”指明创建一个命名管道且存取权限为0666,即创建者、与创建者同组的用户、其他用户对该命名管道的访问权限都是可读可写( 这里要注意umask对生成的管道文件权限的影响 )。
命名管道创建后就可以使用了,他和管道的用法基本一致,就是明明管的要先用open()打开,因为命名管道是存储在硬盘上的一个文件,匿名管道是存在内存中的一个特殊文件。
调用open()打开命名管道的进程可能会被阻塞。但如果同时用读写方式
O_RDWR 打开,则一定不会导致阻塞;如果以只读方式O_RDONLY打开,则调用open()函数的进程将会被阻塞直到有写方打开管道;同样以写方式(O_WRONLY)打开也会阻塞直到有读方式打开管道。
下面代码在server端创建明明管道进行读,client端进行写
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
umask(0);
if(mkfifo("./mypipe",0666|S_IFIFO)<0)
{
perror("mkfifo");
return -1;
}
int fd =open("./mypipe",O_RDONLY);
if(fd<0)
{
perror("open");
return -2;
}
char buf[1024];
while(1)
{
ssize_t s=read(fd,buf,sizeof(buf)-1);
if(s>0)
{
buf[s]=0;
printf("client say# %s\n",buf);
}
else if(s==0)
{
printf("client is quit!server quit too!\n");
break;
}
}
close(fd);
return 0;
}
client.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main()
{
int fd =open("./mypipe",O_WRONLY);
if(fd<0)
{
perror("open");
return -1;
}
char buf[1024];
while(1)
{
printf("Please Enter:");
fflush(stdout);
ssize_t s=read(0,buf,sizeof(buf)-1);
if(s>0)
{
buf[s-1]=0;
write(fd,buf,strlen(buf));
}
}
close(fd);
return 0;
}