Linux进程间通信(二)

时间:2022-01-31 19:05:08
一、概念

  匿名管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信,在命名管道(named pipe或FIFO)提出后,该限制得到了克服。 FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。值得注意的FIFO(first input first output)总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出。

二、命名管道的创建与读写
Linux下有两种方式创建命名管道。一是在Shell下交互地建立一个命名管道,二是在程序中使用系统函数建立命名管道。Shell方式下可使用mknodmkfifo命令,下面命令使用mknod创建了一个命名管道:
mknod namedpipe
创建命名管道的系统函数有两个:mknodmkfifo。两个函数均定义在头文件sys/stat.h中函数原型如下:

#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);

函数mknod参数中path为创建的命名管道的全路径名:mod为创建的命名管道的模式,指明其存取权限;dev为设备值,该值取决于文件创建的种类,它只在创建设备文件时才会勇到。这两个函数调勇成功都返回0,失败都返回-1。下面使勇mknod函数创建了一个命名管道:

umask(0);
if (mknod("/tmp/fifo",S_IFIFO | 0666) == -1)
{
perror("mkfifo error");
exit(1);
}
函数mkfifo前两个参数的含义和mknod相同。下面是使用mkfifo的示例代码:
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)打开
也会阻塞直到有读方式打开管道。
实现:
client.c
 1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<unistd.h>
4 #include<sys/stat.h>
5 #include<fcntl.h>
6 #include<sys/types.h>
7 #include<errno.h>
8 #include<string.h>
9
10 int main()
11 {
12 int fd=open("./myfifo",O_WRONLY);
13 if(fd<0)
14 {
15 perror("open");
16 return 1;
17 }
18 char buf[1024];
19 while(1)
20 {
21 memset(buf,'\0',sizeof(buf));
22 printf("Please Enter: ");
23 fflush(stdout);
24 ssize_t _s=read(1,buf,sizeof(buf));
25 if(_s>0)
26 {
27 buf[_s-1]='\0';
28 write(fd,buf,strlen(buf));
29 }
server.c
 1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<sys/types.h>
4 #include<sys/stat.h>
5 #include<fcntl.h>
6 #include<string.h>
7 #include<errno.h>
8
9 int main()
10 {
11 if(mkfifo("./myfifo",S_IFIFO|0644)<0)
12 {
13 perror("mkfifo");
14 return 1;
15 }
16 int fd=open("./myfifo",O_RDONLY);
17 if(fd<0)
18 {
19 perror("open");
20 return 2;
21 }
22 char buf[1024];
23 while(1)
24 {
25 memset(buf,'\0',sizeof(buf));
26 ssize_t _s=read(fd,buf,sizeof(buf)-1);
27 if(_s>0)
28 {
29 printf("client: %s\n",buf);
运行结果:
Linux进程间通信(二)