Chinaunix首页 | 论坛 | 博客
  • 博客访问: 402016
  • 博文数量: 124
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 872
  • 用 户 组: 普通用户
  • 注册时间: 2018-03-29 14:38
个人简介

默默的一块石头

文章分类

全部博文(124)

文章存档

2022年(26)

2021年(10)

2020年(28)

2019年(60)

我的朋友

分类: LINUX

2019-04-22 10:55:33

1.管道概述

管道是Linux中进程间通信的一种方式。这里所说的管道主要指无名管道,它具有如下特点。

    它只能用于具有亲缘关系的进程之间的通信(也就是父子进程或者兄弟进程之间)。

    它是一个半双工的通信模式,具有固定的读端和写端。

    管道也可以看成是一种特殊的文件,对于它的读写也可以使用普通的read()write()等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内核的内存空间中。

2.管道系统调用

 管道创建与关闭说明

管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fds[0]fds[1],其中fds[0]固定用于读管道,而fd[1]固定用于写管道,如图8.3所示,这样就构成了一个半双工的通道。


8.3  Linux中管道与文件描述符的关系

管道关闭时只需将这两个文件描述符关闭即可,可使用普通的close()函数逐个关闭各个文件描述符。



3.管道读写说明

用pipe()函数创建的管道两端处于一个进程中,由于管道是主要用于在不同进程间通信的,因此这在实际应用中没有太大意义。实际上,通常先是创建一个管道,再通过fork()函数创建一子进程,该子进程会继承父进程所创建的管道,这时,父子进程管道的文件描述符对应关系如图8.4所示。

此时的关系看似非常复杂,实际上却已经给不同进程之间的读写创造了很好的条件。父子进程分别拥有自己的读写通道,为了实现父子进程之间的读写,只需把无关的读端或写端的文件描述符关闭即可。例如在图8.5中将父进程的写端fd[1]和子进程的读端fd[0]关闭。此时,父子进程之间就建立起了一条子进程写入父进程读取的通道。

    


    8.4 父子进程管道的文件描述符对应关系    图8.5关闭父进程fd[1]和子进程fd[0]

同样,也可以关闭父进程的fd[0]和子进程的fd[1],这样就可以建立一条父进程写入子进程读取的通道。另外,父进程还可以创建多个子进程,各个子进程都继承了相应的fd[0]fd[1],这时,只需要关闭相应端口就可以建立其各子进程之间的通道。
(把管道的读写方向规定死了)


4.管道使用实例

在本例中,首先创建管道,之后父进程使用fork()函数创建子进程,之后通过关闭父进程的读描述符和子进程的写描述符,建立起它们之间的管道通信。


/* pipe.c */

#include unistd.h

#include sys/types.h

#include errno.h

#include stdio.h

#include stdlib.h


#define MAX_DATA_LEN   256

#define DELAY_TIME 1


int main()

{

    pid_t pid;

    int pipe_fd[2];

    char buf[MAX_DATA_LEN];

    const char data[] = "Pipe Test Program";

    int real_read, real_write;


    memset((void*)buf, 0, sizeof(buf));

    /* 创建管道 */

    if (pipe(pipe_fd) < 0)

    {

        printf("pipe create error\n");

        exit(1);

    }


    /* 创建一子进程 */

    if ((pid = fork()) == 0)

    {

        /*子进程关闭写描述符并通过使子进程暂停1s等待父进程已关闭相应的读描述符 */

        close(pipe_fd[1]);

        sleep(DELAY_TIME * 3);


        /* 子进程读取管道内容 */

        if ((real_read = read(pipe_fd[0], buf, MAX_DATA_LEN)) > 0)

        {

            printf("%d bytes read from the pipe is '%s'\n", real_read, buf);

        }


        /* 关闭子进程读描述符 */

        close(pipe_fd[0]);

        exit(0);

    }

    else if (pid > 0)

    {

        /*父进程关闭读描述符,并通过使父进程暂停1s等待子进程已关闭相应的写描述符 */

        close(pipe_fd[0]);

        sleep(DELAY_TIME);


        if((real_write = write(pipe_fd[1], data, strlen(data))) !=  -1)

        {

            printf("Parent wrote %d bytes : '%s'\n", real_write, data);

        }


        /*关闭父进程写描述符*/

        close(pipe_fd[1]);


        /*收集子进程退出信息*/

        waitpid(pid, NULL, 0);

        exit(0);

    }

}


将该程序交叉编译,下载到开发板上的运行结果如下所示:

 

$ ./pipe

Parent wrote 17 bytes : 'Pipe Test Program'

17 bytes read from the pipe is 'Pipe Test Program'


阅读(1530) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~