FIFO(first in, first out),是一个半双工数据流,也即一个半双工管道。不同于匿名管道的是,每个FIFO有一个路径名(或文件名)与之关联,也即FIFO的名字。有了名字,无亲缘关系的进程间就可以通过管道进行数据传输了。
创建FIFO的方式:
- 使用shell命令 mkfifo创建一个有名管道
- 使用C库函数mkfifo创建一个有名管道
使用shell命令 mkfifo创建一个有名管道
1
[infor@s123 FIFO]$
mkfifo
npipe
2
[infor@s123 FIFO]$
ls
-l
3
prw-r--r-- 1 infor app 0 Nov 13 11:32 npipe
上面我们创建了一个有名管道npipe,我们可以看到有名管道其实是一个文件,文件类型是“p”,管道类型。
我们在开启两个终端,分别为A和B。在A终端下将数据写入管道,在B终端下将数据读出来。
1
[infor@s123 FIFO]$
ping
10.4.123.124 >> npipe
2
在终端A下将ping的结果写入管道npipe,这里会一直阻塞到另一个进程将数据全部读出或中止读出。
1
[infor@s123 FIFO]$
cat
npipe
2
PING 10.4.123.124 (10.4.123.124) 56(84) bytes of data.
3
64 bytes from 10.4.123.124: icmp_seq=0 ttl=128
time
=0.838 ms
4
64 bytes from 10.4.123.124: icmp_seq=1 ttl=128
time
=0.835 ms
5
64 bytes from 10.4.123.124: icmp_seq=2 ttl=128
time
=0.843 ms
6
64 bytes from 10.4.123.124: icmp_seq=3 ttl=128
time
=0.834 ms
在终端B下读取npipe。
使用C库函数mkfifo创建一个有名管道
1
#include <sys/types.h>
2
#include <sys/stat.h>
3
4
5
6
7
int
mkfifo(
const
char
*pathname, mode_t mode);
对于创建方式,mkfifo隐含指定O_CREAT|O_EXCL,也即mkfifo创建一个新的FIFO,如果该FIFO已经存在,则会返回EEXIST错误。
对于参数mode可有如下选项:
S_IRUSR:当前用户可读
S_IWUSR:当前用户可写
S_IRGRP:组成员可读
S_IWGRP:组成员可写
S_IROTH:其他用户可读
S_IWOTH:其他用户可写
下面通过例子看下如何使用。
假如有这样一个案例。进程A执行完将执行结果写入管道,等待进程B将该结果读出。
01
#include <stdio.h>
02
#include <stdlib.h>
03
#include <sys/types.h>
04
#include <sys/stat.h>
05
#include <unistd.h>
06
#include <fcntl.h>
07
#include <errno.h>
08
09
#define FIFO_NAME ("/tmp/fifo.1") // 设定FIFO的名字
10
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) // 设定创建FIFO的权限
11
12
13
int
main()
14
{
15
int
writefd;
16
char
status[] =
"success"
;
17
size_t
n = 0;
18
19
20
if
(mkfifo(FIFO_NAME, FILE_MODE) < 0)
21
{
22
if
(EEXIST ==
errno
)
23
{
24
printf
(
"FIFO:%s已经存在,不能重新创建\r\n"
, FIFO_NAME);
25
}
26
else
27
{
28
perror
(
"创建FIFO错误"
);
29
exit
(1);
30
}
31
}
32
33
34
writefd = open(FIFO_NAME, O_WRONLY, 0);
35
if
(-1 == writefd)
36
{
37
perror
(
"打开FIFO失败"
);
38
unlink(FIFO_NAME);
39
exit
(1);
40
}
41
42
43
n = write(writefd, status,
strlen
(status));
44
if
(n !=
strlen
(status))
45
{
46
perror
(
"写入FIFO失败"
);
47
unlink(FIFO_NAME);
48
exit
(1);
49
}
50
51
if
(-1 == close(writefd))
52
{
53
perror
(
"关闭FIFO失败"
);
54
unlink(FIFO_NAME);
55
exit
(1);
56
}
57
58
return
0;
59
}
编译并执行:
1
[infor@s123 FIFO]$ gcc -o wnpipe wnpipe.c
2
[infor@s123 FIFO]$ ./wnpipe
3
这里我们看一下/tmp/fifo.1 是否生成:
1
[infor@s123 tmp]$
ls
-l /tmp/fifo.1
2
prw-r--r-- 1 infor app 0 Nov 13 12:58 /tmp/fifo.1
我们看到FIFO文件已经生成。
01
#include <stdio.h>
02
#include <stdlib.h>
03
#include <sys/types.h>
04
#include <sys/stat.h>
05
#include <unistd.h>
06
#include <fcntl.h>
07
#include <errno.h>
08
09
#define FIFO_NAME ("/tmp/fifo.1") // 设定FIFO的名字
10
#define MAXLINE (1024)
11
12
13
int
main()
14
{
15
int
readfd;
16
char
status[MAXLINE];
17
size_t
n = 0;
18
19
20
readfd = open(FIFO_NAME, O_RDONLY, 0);
21
if
(-1 == readfd)
22
{
23
perror
(
"打开FIFO失败"
);
24
unlink(FIFO_NAME);
25
exit
(1);
26
}
27
28
29
n = read(readfd, status, MAXLINE);
30
if
(-1 == n)
31
{
32
perror
(
"读取FIFO失败"
);
33
exit
(1);
34
}
35
36
printf
(
"管道内容:%s\r\n"
, status);
37
38
39
if
(-1 == close(readfd))
40
{
41
perror
(
"关闭FIFO失败"
);
42
unlink(FIFO_NAME);
43
exit
(1);
44
}
45
46
47
unlink(FIFO_NAME);
48
49
return
0;
50
}
编译并执行:
1
[infor@s123 FIFO]$ gcc -o rnpipe rnpipe.c
2
[infor@s123 FIFO]$ ./rnpipe
3
管道内容:success
这里我们再看一下/tmp/fifo.1 是否还存在:
1
[infor@s123 tmp]$
ls
-l /tmp/fifo.1
2
ls
: /tmp/fifo.1: No such
file
or directory
可以看到文件已被删除了。
2011-11-13 任洪彩 qdurenhongcai@163.com
转载请注明出处。