【linux高级程序设计】(第九章)进程间通信-管道 3

有名管道

无名管道和有名管道:

1. 管道是特殊类型的文件,在满足先入先出的原则写可以读写,不能定位读写位置。

2.管道是单向的。

3.无名管道阻塞于读写位置,而有名管道阻塞在创建位置

4.无名管道一般只用于亲缘关系进程间通信;有名管道以磁盘文件的方式存在,可以实现本机任意两进程间通信。

shell创建有名管道

mknod 管道名 p  //创建名为PIPETEST的有名管道 mknod为命令 p是参数,表示有名管道

指令 > 管道名 &   //将指令结果输入到到管道文件中

指令 < 管道名      //以指定管道名中的内容做为输入

编程实现有名管道

int mkfifo (__const char *__path, __mode_t __mode):建立的有名管道文件必须之前不存在, mode是该文件的权限。成功返回0,否则返回-1.

通过read(), write()实现读写操作。

其阻塞方式见下图(我懒得打字了,就上图吧....)

例子:

写进程

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

#define FIFO_NAME "/tmp/my_fifo"       //要创建的有名管道的路径
int main(int argc, char * argv[])
{
    int pipe_fd;
    int res;
    char buffer[] = "hello world!";
    if(access(FIFO_NAME, F_OK) == -1)   //文件是否存在
    {
        res = mkfifo(FIFO_NAME, 0766);    //创建管道
        if(res != 0)
        {
            fprintf(stderr, "Could not create fifo %s
", FIFO_NAME);
            exit(EXIT_FAILURE);
        }
    }
    printf("Process %d opening FIFO O_WRONLY
", getpid());
    pipe_fd = open(FIFO_NAME, O_WRONLY);    //打开有名管道
    printf("the file's descriptor is %d
", pipe_fd);
    if(pipe_fd != -1)
    {
        res = write(pipe_fd, buffer, sizeof(buffer));  //写数据
        if(res == -1)
        {
            fprintf(stderr, "Write error on pipe
");
            exit(EXIT_FAILURE);
        }
        printf("write data is %s, %d bytes is write
", buffer, res);
        close(pipe_fd);
    }
    else
        exit(EXIT_FAILURE);
    printf("Process %d finished
", getpid());
    exit(EXIT_SUCCESS);
}

读进程

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

#define FIFO_NAME "/tmp/my_fifo"       //要创建的有名管道的路径
int main(int argc, char * argv[])
{
    int pipe_fd;
    int res;
    char buffer[4096];
    int bytes_read = 0;
    memset(buffer, '', sizeof(buffer));
    printf("Process %d opening FIFO O_RDONLY
", getpid());
    pipe_fd = open(FIFO_NAME, O_RDONLY);    //打开有名管道
    printf("the file's descriptor is %d
", pipe_fd);
    if(pipe_fd != -1)
    {
        bytes_read = read(pipe_fd, buffer, sizeof(buffer));
        printf("the read data is %s
", buffer);
        close(pipe_fd);
    }
    else
        exit(EXIT_FAILURE);
    printf("Process %d finished, %d bytes read
", getpid(), bytes_read);
    exit(EXIT_SUCCESS);
}

运行时,先在一个终端运行写进程,此时写进程会阻塞。

ctrl+alt+[F1-F6]切换终端,在新终端运行读进程。

读进程端结果为

再切换回原终端,写进程也执行完毕。

原文地址:https://www.cnblogs.com/dplearning/p/4681080.html