linux系统编程之管道(一):匿名管道(pipe)

原文地址:http://www.cnblogs.com/mickole/p/3192210.html





一,什么是管道

管道是Linux支持的最初Unix
IPC形式之一,具有以下特点:

  • 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
  • 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

  • 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。

  • 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。

管道的实现机制:

管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。





二,管道的创建(pipe)

包含头文件<unistd.h>

功能:创建一无名管道

原型:





1

int pipe(int
fd[2]);

参数:

fd:文件描述符数组,其中fd[0]表示读端,
fd[1]表示写端

返回值:成功返回0,失败返回错误代码

man帮助说明:





1

2

3

4

5

6

7

8

DESCRIPTION      

       pipe() creates a pipe, a unidirectional data channel that can be used

       for
interprocess communication.  The array pipefd is used to return

       two file descriptors referring to the ends of the pipe.  pipefd[0]

       refers to the read end of the pipe.  pipefd[1] refers to the write

       end of the pipe.  Data written to the write end of the pipe is

       buffered by the kernel until it is read from the read end of the

       pipe.  For further details, see pipe(7).

该函数创建的管道的两端处于一个进程中间,在实际应
用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个
进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。父子进程间具有相同的文件描述符,且指向同一个管道pipe,其他没有关系的进程不能获得pipe()产生的两个文件描述符,也就不能利用同一个管道进行通信。

创建管道后示意图:





三,利用管道进行父子进程间数据传输

示例一:子进程向管道中写数据,父进程从管道中读出数据





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

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <fcntl.h>

int main(void)

{

    int
fds[2];

    if(pipe(fds) == -1){

        perror("pipe error");

        exit(EXIT_FAILURE);

    }

    pid_t pid;

    pid = fork();

    if(pid == -1){

        perror("fork error");

        exit(EXIT_FAILURE);

    }

    if(pid == 0){

        close(fds[0]);//子进程关闭读端

        write(fds[1],"hello",5);

        exit(EXIT_SUCCESS);

    }

    close(fds[1]);//父进程关闭写端

    char
buf[10] = {0};

    read(fds[0],buf,10);

    printf("receive datas = %s\n",buf);

    return
0;

}

结果:

示例二:利用管道实现ls
|wc –w功能





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

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <fcntl.h>

int main(void)

{

    int
fds[2];

    if(pipe(fds) == -1){

        perror("pipe error");

        exit(EXIT_FAILURE);

    }

    pid_t pid;

    pid = fork();

    if(pid == -1){

        perror("fork error");

        exit(EXIT_FAILURE);

    }

    if(pid == 0){

        

        dup2(fds[1],STDOUT_FILENO);//复制文件描述符且指定新复制的fd为标准输出

        close(fds[0]);//子进程关闭读端

        close(fds[1]);

        execlp("ls","ls",NULL);

        fprintf(stderr,"exec error\n");

        exit(EXIT_FAILURE);

    }

    dup2(fds[0],STDIN_FILENO);

    close(fds[1]);//父进程关闭写端

    close(fds[0]);

    execlp("wc","wc","-w",NULL);

    fprintf(stderr, "error execute wc\n");

    exit(EXIT_FAILURE);

}

结果:

linux系统编程之管道(一):匿名管道(pipe),布布扣,bubuko.com

时间: 2024-10-10 13:39:42

linux系统编程之管道(一):匿名管道(pipe)的相关文章

linux系统编程视频 百度网盘下载

本帖最后由 雇佣兵333 于 2015-5-19 16:15 编辑 c教程目录: Linux开发快速入门培训gcc快速入门Makefile快速入门GDB快速入门 Linux系统编程之文件篇01认识计算机系统(上)计算机系统组成计算机系统硬件组成总线I/O设备内存处理器(运算器+控制器) 02认识计算机系统(下)什么是操作系统Linux内核模块操作系统管理硬件操作系统三个基本抽象进程上下文切换进程虚地址空间虚拟文件系统(VFS) 03系统编程介绍系统编程与应用编程系统资源系统调用系统调用与C库关系

Linux系统编程@进程通信(一)

进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统的一个分支) POSIX进程间通信(POSIX:可移植操作系统接口,为了提高UNIX环境下应用程序的可移植性.很多其他系统也支持POSIX标准(如:DEC OpenVMS和Windows).) 现在Linux使用的进程间通信方式包括: 管道(pipe).有名管道(FIFO) 信号(signal) 消

Linux系统编程札记:进程通信(一) &nbsp; &nbsp;

进程简单来讲就是一个程序的一次执行,这里说的进程一般都指的是运行在用户态的进程,而处于用户态的不同进程之间是彼此相互隔离的,它们必须通过某种方式来进行通信,具体理由如下: (1)数据传输:有时候一个进程需要将它的数据发送给另一个进程. (2)资源共享:有时候多个进程之间需要共享同样的资源. (3)通知事件:有时候一个进程需要向另一个或一组进程发送消息,通知它们发生了某个事件. (4)进程控制:有些进程希望能够完全控制另一个进程的执行,此时控制进程希望能够拦截另一进程的所有操作,并能够及时知道它的

linux系统编程综合练习-实现一个小型的shell程序(四)

上节中已经对后台作业进行了简单处理,基本上要实现的功能已经完了,下面回过头来,对代码进行一个调整,把写得不好的地方梳理一下,给代码加入适当的注释,这种习惯其实是比较好了,由于在开发的时候时间都比较紧,都只是想办法去尽快实现,而肯定会有一些代码是写得不太好的,所以有时间的话最好是从头至尾将整个代码进行梳理,也许在梳理的过程中会发现许多不足的地方,好了,下面开始: 而这个信号安装函数是在init.c中实现的: 接下来进行shell循环: 它的实现是在parse.c中: 如注释所示,可以挪至init.

回顾linux系统编程学习过程

一.基础知识 1.linux操作系统,熟悉常用的指令. 2.vim编译器的使用,Makefile的编写. 3.用户以及权限方面相关的知识. 4.linux下环境变量的概念. 二.进程概念相关 1.进程的概念,了解PCB的概念,以及task_struct结构体. 2.进程的创建,fork()与vfork()的区别和联系. 3.进程的等待,waitpid()与wait(),阻塞等待与非阻塞等待. 4.进程的程序替换,execl(),execlp(),execle(),execv(),execvp()

Linux系统编程之进程间通信

今天我们接着谈Linux系统编程中的进程间的通信,上一节我们讨论了进程的基本操作.这一节我们来讨论一下进程间的通信.        常见的进程间的通信方式有:无名管道.命名管道.信号.共享内存.消息队列.信号量.套接字. 接下来我们先来谈:                一.无名管道:                      1.管道是UNIX系统的IPC的最古老方式,并且多数unix系统都提供此种通信方式..                      2.管道是一种半双工的通信方式,数据只能

Linux系统编程(第2版)笔记 (本书基本上就是Linux C API的简单使用说明,入门级别的)

Linux系统编程(第2版) 跳转至: 导航. 搜索 目录 1 入门和基本概念 2 文件I/O 3 缓冲I/O 4 高级文件I/O 5 进程管理 6 高级进程管理 7 线程 8 文件和目录管理 9 内存管理 10 信号 11 时间(这里谈不上系统编程了,就是C库API) 12 附录A C语言的GCC扩展 13 附录B 参考书目 入门和基本概念 文件I/O read(): EINTR EAGAIN 其他错误:EBADF EFAULT EINVAL EIO Append模式:每次write之前的文件

Linux系统编程【转】

转自:https://blog.csdn.net/majiakun1/article/details/8558308 一.Linux系统编程概论 1.1 系统编程基石 syscall: libc:标准C库.系统调用封装.线程库.基本应用工具 gcc: 1.2 模块接口 API:应用程序编程接口,源代码级别,能通过编译,由标准C语言定义,libc来实现 ABI:应用程序二进制接口,二进制级别,能正常运行,关注调用约定.字节序.寄存器使用.系统调用.链接.二进制格式等,很难实现 1.3 错误处理 <

LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程需要做的什么事情,所以特定看了UNIX环境编程和LINUX系统编程这2本书 重新梳理下整个要点. 内容: 一般而言: 如果程序类似于下面的情况: if((pid=fork())==0) { dochildtthing(); exit(0); } else if(pid>0) { dofathertt