← 返回首页
Linux高级程序设计(五十四)
发表时间:2021-12-07 23:27:31
命名管道读写

由于命名管道在本地创建了一个管道文件,所以系统调用的IO函数都可以操作命名管道,但是不能使用lseek。

命名管道通过管道文件进行读写操作,例如:open()、write()、read()、close()。和无名管道一样,操作命名管道肯定要考虑默认情况下其阻塞特性。

下面验证的是默认情况下的特点,即 open() 的时候没有指定非阻塞标志( O_NONBLOCK )。

open() 以只读方式打开 FIFO 时,要阻塞到某个进程为写而打开此 FIFO open() 以只写方式打开 FIFO 时,要阻塞到某个进程为读而打开此 FIFO。

简单一句话,只读等着只写,只写等着只读,只有两个都执行到,才会往下执行。

实例:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>

#define FIFONAME "myfifo"

int main(int argc, char *argv[])
{
    int ret;

    ret = mkfifo(FIFONAME, 0664); // 创建命名管道
    if (ret != 0)
    { // 出错
        if (errno != EEXIST)
        {
            perror("erro to mkfifo:");
            //printf("errerno=%d\n",errno);  //如果管道已经创建则errno值为17.
            exit(1);
        }
    }

    int fd;
    fd = open(FIFONAME, O_RDWR);
    if (fd == -1)
    {
        perror("error to open:");
        exit(1);
    }

    if (write(fd, "hello,world!\n", strlen("hello,world!\n")) == -1)
    {
        perror("error to write:");
        exit(1);
    }

    write(fd, "welcome to linux world!\n", strlen("welcome to linux world!\n"));

    char buff[128] = "";
    if (read(fd, buff, sizeof(buff)) == -1)
    {
        perror("error to read:");
        exit(1);
    }

    printf("buff=%s\n",buff);

     //再读一次会阻塞
    if (read(fd, buff, sizeof(buff)) == -1)
    {
        perror("error to read:");
        exit(1);
    }

    printf("buff=%s\n",buff);

    close(fd);

    return 0;
}

运行结果:

[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
buff=hello,world!
welcome to linux world!