您的位置:首页 > 运维架构 > Linux

打开文件linux系统编程之管道(三):命名管道FIFO和mkfifo函数

2013-05-21 19:55 337 查看
近期一直在研究打开文件之类的问题,上午正好有机会和大家共享一下.

进程间通信必须通过内核提供的通道,而且必须有一种办法在进程中标识内核提供的某个通道,后面讲过的匿名管道是用打开的文件描述符来标识的。如果要互相通信的几个进程没有从公共先人那里继承文件描述符,它们怎么通信呢?内核提供一条通道不成问题,问题是如何标识这条通道才能使各进程都可以访问它?文件系统中的路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道。

FIFO和UNIX Domain Socket这两种IPC机制都是利用文件系统中的特别文件来标识的。

FIFO文件在磁盘上没有数据块,仅用来标识内核中的一条通道,如 prw-rw-r-- 1 simba simba 0 May 21 10:13 p2,文件类型标识为p表示FIFO,文件大小为0。各进程可以打开这个文件停止read/write,实际上是在读写内核通道(根本原因在于这个file结构体所指向的read、write函数和惯例文件不一样),这样就实现了进程间通信。UNIX Domain Socket和FIFO的原理类似,也须要一个特别的socket文件来标识内核中的通道,例如/run目录下有很多系统服务的socket文件:

srw-rw-rw- 1 root root 0 May 21 09:59 acpid.socket

....................

文件类型s表示socket,这些文件在磁盘上也没有数据块。

一、定名管道(FIFO)

匿名管道应用的一个制约就是只能在拥有独特先人(拥有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为定名管道。

定名管道可以从命令行上创建,命令行方法是使用下面这个命令:
$ mkfifo filename
定名管道也可以从程序里创建,相关函数有:
int mkfifo(const char *filename,mode_t mode);

二、定名管道和匿名管道

匿名管道由pipe函数创建并打开。
定名管道由mkfifo函数创建,打开用open。
FIFO(定名管道)与pipe(匿名管道)之间独一的区别在它们创建与打开的方法不同,这些工作实现之后,它们拥有雷同的语义。

The only difference between pipes and FIFOs is the manner in which they are created and opened. Once these tasks have been accomplished, I/O on pipes and FIFOs has exactly the same semantics.

三、定名管道的打开规则

如果以后打开操纵是为读而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为写而打开该FIFO
O_NONBLOCK enable:立刻返回胜利
如果以后打开操纵是为写而打开FIFO时
O_NONBLOCK disable:阻塞直到有相应进程为读而打开该FIFO
O_NONBLOCK enable:立刻返回失败,错误码为ENXIO

须要注意的是打开的文件描述符默认是阻塞的,大家可以写两个很简单的小程序测试一下,重要也就一条语句

int fd = open("p2", O_WRONLY); 假设p2是定名管道文件,把打开标志换成 O_RDONLY 就是另一个程序了,可以先运行RD程序,此时会阻塞,再在另一个窗口运行WR程序,此时两个程序都会从open返回胜利。非阻塞时也不难测试,open时增长标志位就可以了。

须要注意的是 命令管道与匿名管道的读写规则是一样的,拜见这里

下面示例定名管道实现拷贝文件的功能:

C++ Code

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

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

/*************************************************************************
> File Name: process_.c
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Sat 23 Feb 2013 02:34:02 PM CST
************************************************************************/

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

#include<stdio.h>

#include<stdlib.h>

#include<errno.h>

#include<string.h>

#include<signal.h>

#define ERR_EXIT(m) \

do { \

perror(m); \

exit(EXIT_FAILURE); \

}
while(
0)

int main(
int argc,
char *argv[])

{

mkfifo(
"tp",
0644);

int infd = open(
"Makefile", O_RDONLY);

if (infd == -
1)

ERR_EXIT(
"open error");

int outfd;

outfd = open(
"tp", O_WRONLY);

if (outfd == -
1)

ERR_EXIT(
"open error");

char buf[
1024];

int n;

while ((n = read(infd, buf,
1024)) >
0)

write(outfd, buf, n);

close(infd);

close(outfd);

return
0;

}

每日一道理

风,那么轻柔,带动着小树、小草一起翩翩起舞,当一阵清风飘来,如同母亲的手轻轻抚摸自己的脸庞,我喜欢那种感觉,带有丝丝凉意,让人心旷神怡。享受生活,不一定要有山珍海味、菱罗绸缎为伴,大自然便是上帝所赐予人类最为珍贵的。

程序使用mkfifo函数创建一个定名管道文件tp,将Makefile 的文件都读取到tp文件中。

C++ Code

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

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

/*************************************************************************
> File Name: process_.c
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Sat 23 Feb 2013 02:34:02 PM CST
************************************************************************/

#include<sys/types.h>

#include<sys/stat.h>

#include<unistd.h>

#include<fcntl.h>

#include<stdio.h>

#include<stdlib.h>

#include<errno.h>

#include<string.h>

#include<signal.h>

#define ERR_EXIT(m) \

do { \

perror(m); \

exit(EXIT_FAILURE); \

}
while(
0)

int main(
int argc,
char *argv[])

{

int outfd = open(
"Makefile2", O_WRONLY | O_CREAT | O_TRUNC,
0644);

if (outfd == -
1)

ERR_EXIT(
"open error");

int infd;

infd = open(
"tp", O_RDONLY);

if (infd == -
1)

ERR_EXIT(
"open error");

char buf[
1024];

int n;

while ((n = read(infd, buf,
1024)) >
0)

write(outfd, buf, n);

close(infd);

close(outfd);

unlink(
"tp");
// delete a name and possibly the file it refers to

return
0;

}

可以看到跟上面的程序是相反的,即从tp读取到Makefile2,实现拷贝文件的功能,这里用到了一个unlink函数,属于inode_operations系列的一个函数,即inode引用计数减1,当引用计数为0且进程已经关闭文件描述符时,文件将被删除。

文章结束给大家分享下程序员的一些笑话语录:

Bphone之你们聊,我先走了!移动说:我在phone前加o,我叫o缝;苹果说:我在phone前i,我是i缝;微软说:我在phone前加w,我叫w缝;三星说:你们聊,我先走了!

将来王建宙写回忆录的时候,一定要有一句“常小兵为中国移动的发展做出了不可磨灭的贡献”。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: