Linux进程间通信之二:有名管道FIFO

有名管道FIFO是一个特殊文件。但并不是将信息真正存到磁盘,而是存到内存中。
两个完全没有关联的进程,通过访问这个管道文件,实现进程间通信。

头文件

#include <sys/types.h>
#include<sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);

使用方式

  1. 创建一个FIFO文件:mkfifo(“/tmp/fifo”,0766)。
  2. A进程以写方式打开FIFO文件:open(FIFO文件,O_WRONLY),调用write往里写数据。
  3. B进程以读方式打开FIFO文件:open(FIFO文件,O_RDONLY),调用read读出数据。

阻塞现象

  1. A进程以写(读)方式打开FIFO,将会阻塞在open(),直到B以读(写)方式打开FIFO。
  2. 默认方式下,若管道没有数据,读操作阻塞,直到有数据被写入。
  3. 默认方式下,若管道数据满了,写操作阻塞,直到有数据被读出。

实例代码

程序fifo_write向管道写入数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>

#define FIFO "/tmp/fifo"

int main(int argc,char *argv[])
{
int pipe_fd;
int res;
char buffer[]="helloworld!";
res=mkfifo(FIFO,0766);
printf("PID %d opening FIFO O_WRONLY.\n",getpid());

pipe_fd=open(FIFO,O_WRONLY);
printf("pipe_fd=%d.\n",pipe_fd);
if(pipe_fd!=-1)
res=write(pipe_fd,buffer,sizeof(buffer));
printf("PID %d finished.\n",getpid());
return 0;
}

程序fifo_read从管道读出数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

#define FIFO "/tmp/fifo"
int main(int argc,char *argv[])
{
int pipe_fd;
int bytes_read=0;
char buffer[4096];
memset(buffer,'\0',4096);
printf("PID %d opening FIFO O_WRONLY.\n",getpid());

pipe_fd=open(FIFO,O_RDONLY);
printf("pipe_fd=%d.\n",pipe_fd);
if(pipe_fd!=-1)
{
bytes_read=read(pipe_fd,buffer,sizeof(buffer));
printf("read data:%s\n",buffer);
}
printf("PID %d finished.\n",getpid());
return 0;
}

运行结果

先在A窗口执行fifo_write,结果如下:

1
2
tao@taohi-xubuntu:~$ ./fifo_write
PID 5163 opening FIFO O_WRONLY.

根据前面提到的阻塞现象,fifo_write阻塞在open()。

然后在B窗口执行fifo_read,结果如下:

1
2
3
4
5
tao@taohi-xubuntu:~$ ./fifo_read
PID 5165 opening FIFO O_WRONLY.
pipe_fd=3.
read data:helloworld!
PID 5165 finished.

此时观察B窗口,不再被阻塞,结果如下:

1
2
3
4
tao@taohi-xubuntu:~$ ./fifo_write
PID 5163 opening FIFO O_WRONLY.
pipe_fd=3.
PID 5163 finished.