一.管道

管道的名称很形象,它就像是一个水管,我们从一端到水然后水从令一端流出。不同的是这里说的管道的两边都是进程。从一端往管道里写数据,其它进程可以从管道的另一端的把数据读出,从而实现了进程间通信的功能。

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

1.管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;

2.只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);

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

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

1.1管道的创建

管道是由调用pipe函数而创建的。

1.

名称::

pipe

功能:

创建管道

头文件:

#include <unistd.h>

函数原形:

int pipe(int filedes[2]);

参数:

返回值:

若成功返回0,若出错则返回-1

Linux用函数pipe来创建管道,经由参数filedes返回两个文件描述符:filedes[0]为读而打开,filedes[1]为写而打开。filedes[1]的输出是filedes[0]的输入。

/*14_1.c*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h> int main()
{
int n;
int fd[];
pid_t pid;
char line[]; if(pipe(fd)<) /*建立管道*/
perror(“pipe error”);
if((pid=fork())<) /*创建子进程*/
perror(“fork error”);
else if(pid==) /*如果是子进父程*/
{
close(fd[]); /*关闭读描述符*/
write(fd[],”I’m child,hello father!”,);/*往管道里写数据*/
}
else /*如果是父进程*/
{
close(fd[]); /*关闭写描述符*/
wait(); /*等待子进程结束*/
n=read(fd[],line,); /*从管道里读数据,读到缓冲数组中*/
write(STDOUT_FILENO,line,n); /*把缓冲区的数据写道屏幕上*/
}
exit();
}

注意,默认情况下,read函数回阻塞到有数据可读为止。

程序先创建一个管道,而后创建一个子进程。让父进程向管道里写数据,让子进程从管道读数据,程序在写个读之前都把不用的描述符关掉。这要做的好处是提高了安全性,因为如果父子进程同时往管道里写将发生错误。程序的运行结果是 I’m father, hello child!

1.2管道的读写规则

管道两端可分别用描述字fd[0]以及fd[1]来描述,需要注意的是,管道的两端是固定了任务的。即一端只能用于读,由描述字fd[0]表示,称其为管道读端;另一端则只能用于写,由描述字fd[1]来表示,称其为管道写端。如果试图从管道写端读取数据,或者向管道读端写入数据都将导致错误发生。一般文件的I/O函数都可以用于管道,如close、read、write等等。

从管道中读取数据:如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0; 当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。

向管道中写入数据:向管道中写入数据时,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。

注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。

1.3管道的局限性

管道的主要局限性正体现在它的特点上:

只支持单向数据流;

只能用于具有亲缘关系的进程之间;

没有名字;

管道的缓冲区是有限的(管道制存在于内存中,在管道创建时,为缓冲区分配一个页面大小);

管道所传送的是无格式字节流,这就要求管道的读出方和写入方必须事先约定好数据的格式,比如多少字节算作一个消息(或命令、或记录)等等;

1.4管道的其它操作函数

poen pclose创建和关闭无名管道

Linux下标准I/O函数库提供了poen函数,它创建了一个管道并启动另外一个进程,该进程或者从管道读出标准输入,或者从管道写入标准输出。

#include <stdio.h>

FILE *poen(const char *command,const char *type);

//返回:成功时为文件指针,出错时为NULL

int pclose(FILE *stream);

//返回:成功时为shell的终止状态,出错时为-1

其中command是一个shell命令行,它是由shell程序处理的,poen在调用进程和所指定的命令之间创建一个管道,由open返回的值是一个标准I/O FILE指针,该指针或者用于输入,或者用于输出,具体取决于字符串type,如果type为r,那么调用进程读取command的标准输出。如果type为w,那么调用进程写到command的标准输入。pclose函数关闭由poen创建的标准I/O流stream,等待其中的命令终止,然后返回shell的终止状态。

这两个函数执行过程是:先创建一个管道,调用fork产生一个子进程,然后关闭管道的不使用端,执行一个shell以运行命令,然后等待命令终止。

函数popen先执行fork,然后调用exec以执行cmdstring,并且返回一个标准I/O文件指针。如果type是“r”,则文件指针连接到cmdstring的标准输出。如果type是”w”,则文件指针连接到cmdstring的标准输入。

UNIX网络编程卷2进程间通信读书笔记(二)—管道 (1)的更多相关文章

  1. UNIX网络编程卷2进程间通信读书笔记(一)—概述

    http://blog.chinaunix.net/uid-12868584-id-92807.html 写的灰常好,我就转载了 一.什么是进程间通信 IPC是进程间通信的简称,所谓进程通信,就是不同 ...

  2. UNIX 网络编程第五章读书笔记

    刚看完 UNIX 第五章内容,我想按照自己的方式将自己获得的知识梳理一遍,以便日后查看!先贴上一段简单的 TCP 服务器端代码: #include <sys/socket.h> #incl ...

  3. UNIX网络编程 卷2:进程间通信

    这篇是计算机类的优质预售推荐>>>><UNIX网络编程 卷2:进程间通信(第2版)> UNIX和网络专家W. Richard Stevens的传世之作 编辑推荐 两 ...

  4. Unix网络编程--卷二:进程间通信

    Unix网络编程--卷二:进程间通信 本书是一部Unix网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机网络应用程序的必要条件.本书从对Po ...

  5. [转载] 读《UNIX网络编程 卷1:套接字联网API》

    原文: http://cstdlib.com/tech/2014/10/09/read-unix-network-programming-1/ 文章写的很清楚, 适合初学者 最近看了<UNIX网 ...

  6. 《UNIX网络编程 卷1》之"学习环境搭建"(CentOS 7)

    <UNIX网络编程 卷1>的源码可以从www.unpbook.com下载得到.解压之后的目录为unpv13e. 详细步骤 编译 进入unpv13e目录,按如下步骤编译: ./configu ...

  7. UNIX网络编程卷1 - >环境搭建(ubuntu16.04)

      学习unp网络编程,树上的例子均存在#include“unp.h”,故需要对环境进行配置. 1.到资源页下载www.unpbook.com 2.解压并将unpv13e移动到相应的文件夹下 (因为我 ...

  8. 【unp】unix网络编程卷1-->环境搭建(ubuntu14.04)

    学习unp网络编程,树上的例子均存在#include "unp.h",故需要对环境进行配置. 1. 到资源页下载unpv13e 2. 解压并将unpv13e 移动到相应的文件夹下 ...

  9. 《Unix网络编程卷1:套接字联网API》读书笔记

    第一部分:简介和TCP/IP 第1章:简介 第2章:传输层:TCP.UDP和SCTP TCP:传输控制协议,复杂.可靠.面向连接协议 UDP:用户数据报协议,简单.不可靠.无连接协议 SCTP:流控制 ...

随机推荐

  1. 【动态规划/多重背包问题】POJ2392-Space Elevator

    方法同POJ1014-Dividing,唯一不同点在于每一种block有最大限定高度a,故要以a为关键字进行排序,使得最大高度小的在前,否则最大高度小的再后可能放不上去. #include<io ...

  2. Android签名有什么作用?

    应用程序升级:如果你希望用户无缝升级到新的版本,那么你必须用同一个证书进行签名.这是由于只有以同一个证书签名,系统才会允许安装升级的应用程序.如果你采用了不同的证书,那么系统会要求你的应用程序采用不同 ...

  3. 【美】范·K·萨普曼 - 通向财务自由之路(2013年11月26日)

    <通向财务自由之路> 作 者:[美]范·K·萨普曼  译 者:董梅 系 列: 出 版:机械工业出版社 字 数:约40千字 阅读完成:2013年11月26日

  4. MariaDB 主从复制

    MySQL Replication:NySQL复制,MySQL的复制默认为异步工作模式    mysql的复制功能是mysql内置的,装上它之后就具备了这个功能,而mysql复制是mysql实现大规模 ...

  5. webstrom内置压缩工具YUI-compressor详解

    压缩工具层次不穷,各有优点,选择适合的压缩工具为将来做项目开发使用是一件很重要的事情!!在这介绍YUI-compressor 英文官网:http://yui.github.io/yuicompress ...

  6. Boost Converter

    Single Inductor Buck-Boost Converter in Tiny WCSP The TPS63036 is a non inverting buck-boost convert ...

  7. HDU 1159 &amp;&amp; POJ 1458

    最长公共子序列.状态转移方程见代码. #include <iostream> #include <cstdio> #include <cstring> using ...

  8. jQuery EasyUI 数据网格 - 条件设置行背景颜色

    $('#tt').datagrid({ rowStyler:function(index,row){ if (row.listprice>50){ return 'color:blue;font ...

  9. python -m xxx.py和python xxx.py的区别

    先看下python -m site作用是显示sys.path的值内容,也就是python搜索模块的目录,作用类似于linux下的PATH python -m SimpleHTTPServer 会在sy ...

  10. Ubuntu 字体设置:使用Windows 字体

    基础知识 Sans-serif=无衬线体=黑体:并不是具体一款字体,而是一类字体,选择它其实等于选择这类字体中优先级最高的那款字体. Serif=衬线体=白体:同上 Monospace=等宽字体,意思 ...