linux c语言编程,使用mkfifo创建FIFO特殊文件,用于进程间通信

使用 mkfifo 创建一个 FIFO 特殊文件,可用于进程间通信。这种特殊文件,不占磁盘空间,但是可以像普通文件一样读写。

mkfifo 函数简介

mkfifo 的原型和所需头文件如下:

#include <sys/types.h>
#include <sys/stat.h>

 int mkfifo(const char *pathname, mode_t mode);

mkfifo 的返回值

成功返回 0,失败返回 -1,失败码可从 errno 查询。

mkfifo 功能

mkfifo() 函数创建一个名为 pathname 的 FIFO 特殊文件,mode 参数用于指定权限。创建的 FIFO 特殊文件与管道是类似的,都可以用于进程间通信。这种特殊的FIFO文件可以被文件系统加载,因此可以像普通文件一样读写和删除。

使用mkfifo函数创建了FIFO特殊文件后,任何进程都可以像普通文件一样打开之,并读写。通常,读取FIFO特殊文件会被阻塞,直到有进程写入数据到FIFO文件。

mkfifo 函数的简单使用 demo

以下的 demo,首先创建了一个FIFO特殊文件,然后 fork 出一个子进程。父进程延时1秒后,往FIFO文件写入 "https://blog.popkx.com\n",然后使用waitpid函数等待子进程结束。子进程则从FIFO文件读取数据,并且将读出的数据打印到终端。

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

#define FIFO       "blog_popkx_com"

int main()
{
    char buffer[80];
    int fd;
    char s[] = "https://blog.popkx.com\n";

    unlink(FIFO);
    mkfifo(FIFO, 0666);

    switch(fork())
    {
        case -1: 
            printf("fork failed\n"); 
            break;
        case 0:
            fd = open(FIFO, O_RDONLY);
            int len = read(fd, buffer, 80);
            printf("\nlen: %d, %s\n", len, buffer);

            close(fd);
            break;
        default:
            sleep(1);
            fd = open(FIFO, O_WRONLY);
            write(fd, s, sizeof(s));
            close(fd);

            int childRet = 0;
            waitpid(-1, &childRet, 0);

            unlink(FIFO);
            break;
    }

    return 0;
}

编译之,执行结果如下:

$ gcc fifo.c 
$ ./a.out 

len: 24, https://blog.popkx.com

子进程的读取操作被阻塞,直到父进程往FIFO特殊文件写入数据,子进程才从中读出数据,并且打印到终端。

对 FIFO 特殊文件的进一步测试

在子进程中加入延时,如下:

...
 switch(fork())
    {
        case -1: 
            printf("fork failed\n"); 
            break;
        case 0:
            sleep(10);      //  加入适当延时,便于其他测试
            fd = open(FIFO, O_RDONLY);
            int len = read(fd, buffer, 80);
            printf("\nlen: %d, %s\n", len, buffer);
...

这样一来,就会有一段时间FIFO文件里有父进程写入的数据,而子进程还没有将之读出。我们在这段时间里,先查看其占用磁盘空间:

$ ls -ahl
total 24K
drwxrwxr-x  2 lcc lcc 4.0K 10月 18 19:50 .
drwxrwxr-x 14 lcc lcc 4.0K 10月 18 18:50 ..
-rwxrwxr-x  1 lcc lcc 9.0K 10月 18 19:50 a.out
prw-rw-r--  1 lcc lcc    0 10月 18 19:50 blog_popkx_com          # 占用磁盘空间为 0
-rw-rw-r--  1 lcc lcc  754 10月 18 19:50 fifo.c
$ 
$ 
$ cat blog_popkx_com 
https://blog.popkx.com

但是可以使用 cat 命令将FIFO文件中的内容读出。接着,发现进程一直阻塞,这是因为FIFO文件中的内容为空了,子进程的读取操作会一直阻塞到别的进程再往FIFO文件写入内容,才会返回,并且将其中的内容读出。而父进程则会一直 wait 到子进程返回。

$ ps -a|grep a.out
 59923 pts/19   00:00:00 a.out
 59924 pts/19   00:00:00 a.out
阅读更多:   C语言 , Linux笔记
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif