一 管道的作用

  通常把一个进程的输出通过管道连接到另一个进程的输入。

二 popen和pclose函数

#include <stdio.h>

FILE *popen(const char *command,      //是要运行的程序名和相应的参数
       const char *open_mode      //必须是“r”或者“w”,如果是其它值,errno将返回EINVAL
       );                  int pclose(FILE *stream_to_close);     

  popen() 函数通过创建一个管道,调用 fork 产生一个子进程,执行一个 shell 以运行命令来开启一个进程。

  pclose()调用只在popen启动的进程结束后才返回,如果调用pclose函数时它仍在运行,pclose调用将等待该进程的结束。

例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> int main(){
FILE *read_fp;          //要读取的文件描述符
char buffer[BUFSIZ+];      //用来存储读到的文件信息
int chars_read;          //实际读取的元素个数 memset(buffer,'\0',sizeof(buffer));    //将数组清零初始化
read_fp=popen("cat test*.c | wc -l","r");  //创建管道,用于显示所有test*.c文件的字数 if(read_fp!=NULL){
chars_read=fread(buffer,sizeof(char),BUFSIZ,read_fp);//从一个文件流中读数据,最多读取count个元素,每个元素size字节,如果调用成功返回实际读取到的元素个数,如果不成功返回 0
while(chars_read>){
buffer[chars_read-]='\0';      //清除回车符
printf("Reading:-\n %s\n",buffer);
chars_read=fread(buffer,sizeof(char),BUFSIZ,read_fp);
}
pclose(read_fp);        //关闭管道
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}

  使用shell的一个不太好的影响:针对每个popen调用,不仅要启动一个被请求的程序,还要启动一个shell,即每个popen调用将多启动两个进程。从节省系统资源的角度来看,popen函数的调用成本略高,而且对目标命令的调用比正常方式要慢一些。

三 pipe函数

#include <unistd.h>
int pipe(int fd[]);

  pipe函数的参数是一个由两个整数类型的文件描述符组成的数组的指针,两个返回的文件描述符以一种特殊的方式连接起来,写到fd[1]的所有数据都可以从fd[0]读回来,数据基于先进先出的原则(FIFO)进程处理。

  对一个已关闭写数据的管道做read调用将返回0而不是阻塞,读取无效的文件描述符将看作是一个错误并返回-1
 
  如果跨越fork调用使用管道,就会有两个不同的文件描述符可以用于向管道写数据,一个在父进程中,一个在子进程中。只有把父子进程中的针对管道的写文件描述符都关闭,管道才会被认为是关闭了,对管道的read调用才会失败。

管道的读写规则:

  1 从管道中读取数据

  • 如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;
  • 当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于 PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据 量)。注:(PIPE_BUF在include/linux/limits.h中定义,不同的内核版本可能会有所不同。Posix.1要求 PIPE_BUF至少为512字节,red hat 7.2中为4096)。

  2 从管道中写入数据

  向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。
  注:只有在管道的读端存在时,向管道中写入数据才有意义。否则,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。

例子:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> int main(){
const char some_data[]="";
int file_pipes[];
int data_processed;
pid_t fork_result; if(pipe(file_pipes)==){
fork_result=fork();
if(fork_result==(pid_t)-){
fprintf(stderr,"Fork failure");
exit(EXIT_FAILURE);
}
if(fork_result==){      //子进程
close();          //关闭标准输入,即键盘输入
dup(file_pipes[]);    //复制一个文件描述符
close(file_pipes[]);    //关闭读操作
close(file_pipes[]);   //关闭写操作 execlp("od","od","-c",(char*));  //利用od查看特殊格式的文件内容,-c表示ASCII字符或反斜杠序列,(char*)0参数作用是终止被调用程序的参数列表
exit(EXIT_FAILURE);
}
else{     //主进程
close(file_pipes[]);  
data_processed=write(file_pipes[],some_data,strlen(some_data));  //写入数据
close(file_pipes[]);
printf("%d - wrote %d bytes\n",getpid(),data_processed);
}
}
exit(EXIT_SUCCESS);
}

  

Linux学习笔记24——进程管道的更多相关文章

  1. Linux学习笔记(六) 进程管理

    1.进程基础 当输入一个命令时,shell 会同时启动一个进程,这种任务与进程分离的方式是 Linux 系统上重要的概念 每个执行的任务都称为进程,在每个进程启动时,系统都会给它指定一个唯一的 ID, ...

  2. Linux学习笔记25——命名管道(FIFO)

    1 命名管道(FIFO) 管道应用的一个重大缺陷就是没有名字,因此只能用于亲缘进程之间的通信.后来从管道为基础提出命名管道(named pipe,FIFO)的概念,该限制得到了克服.FIFO不同于管道 ...

  3. linux学习笔记之进程

    一.基础知识 1:进程. 1,进程ID: 非负整数,具有唯一性. 1)ID=0的进程:调度进程/交换进程.内核的一部分.不执行任何磁盘上的程序. 2)ID=1的进程:init进程. 1-自举结束时,由 ...

  4. linux学习笔记-13.进程控制

    1.查看用户最近登录情况 lastlastlog 2.查看硬盘使用情况 df 3.查看文件大小 du 4.查看内存使用情况 free 5.查看文件系统 /proc 6.查看日志 ls /var/log ...

  5. Linux学习笔记(七) 查询系统

    1.查看命令 (1)man 可以使用 man 命令名称 命令查看某个命令的详细用法,其显示的内容如下: NAME:命令名称 SYNOPSIS:语法 DESCRIPTION:说明 OPTIONS:选项 ...

  6. Linux学习笔记(一) 文件系统

    对于每一个 Linux 学习者来说,了解 Linux 文件系统的结构是十分有必要的 因为在 Linux 中一切皆文件,可以说只有深入了解 Linux 的文件系统,才会对 Linux 有更深刻的理解 L ...

  7. Linux学习笔记(二) 文件管理

    了解 Linux 系统基本的文件管理命令可以帮助我们更好的使用 Linux 系统,以下介绍几个常用的文件管理命令 1.pwd pwd 是 Print Working Directory 的简写,用于显 ...

  8. Linux学习笔记(四) vi编辑器

    一.vi 编辑器 vi 编辑器 (Visual Interface) 是所有 Unix 及 Linux 系统下标准的编辑器,相当于 Windows 系统中的记事本 它有三种模式,分别是: Comman ...

  9. Linux学习笔记(五) 账号管理

    1.用户与组账号 用户账号:包括实际人员和逻辑性对象(例如应用程序执行特定工作的账号) 每一个用户账号包含一个唯一的用户 ID 和组 ID 标准用户是系统安装过程中自动创建的用户账号,其中除 root ...

随机推荐

  1. PHP金字塔的输出

    相信学习语言的最初的时候,学到循环的时候,开始一定有种摸不着头脑,想砸电脑的冲动吧 这里就是记录我当初学习的时候,为了通过这个循环,学习的金字塔的输出 1.首先,要了解一个金字塔的输出就要去看它的表达 ...

  2. ASP.NET MVC 自我总结的便捷开发实例

    前言 工作了这么久了,接触ASP.NET MVC已经很久了,一直都想总结一下它的一些实用的,经常使用的一些技巧,但是因为一直都很懒,也不想总结,所以一直都没有好好写出来,趁着现在有这种冲劲,那么就先把 ...

  3. [时间操作] C#TimeHelper时间格式化帮助类 (转载)

    点击下载 TimeHelper.rar 主要功能如下 .将时间格式化成 年月日 的形式,如果时间为null,返回当前系统时间 .将时间格式化成 时分秒 的形式,如果时间为null,返回当前系统时间 . ...

  4. C#中堆和栈的区别分析(有待更新总结)

    转载:http://blog.csdn.net/zevin/article/details/5721495 一.预备知识-程序的内存分配 一个由C/C++编译的程序占用的内存分为以下几个部分 1.栈区 ...

  5. Script: Who’s using a database link?(找出谁在使用dblink)

    Every once in awhile it is useful to find out which sessions are using a database link in an Oracle ...

  6. Apache虚拟目录

    Apache虚拟目录  1.打开Apache的配置文件httpd.conf,并去掉#Include conf/extra/httpd-vhosts.conf前面的#! 2.在httpd.conf 末尾 ...

  7. 求最低分最高分---c#(冒泡排序的运用)

    // 输入10个人的分数,去掉两个最高两个最低,求平均分 Console.Write("请输入人数:"); int renshu = int.Parse(Console.ReadL ...

  8. 【POJ1811】【miller_rabin + pollard rho + 快速乘】Prime Test

    Description Given a big integer number, you are required to find out whether it's a prime number. In ...

  9. mount的艺术

    在阅读本文之前,我假设你已经对Linux系统下的硬盘.光盘的设备命令规则有所了解,比如sda和sda1的关系,以及hda.sda.fd.cdrom等设备. === 1 我把U盘插到USB口上了,下一步 ...

  10. 【elasticsearch】(2)centos7 超简单安装elasticsearch 的监控、测试的集群工具elasticsearch head

    elasticsearch-head是elasticsearch(下面称ES)比较普遍使用的可监控.测试等功能的集群管理工具,是由H5编写的单独的网页程序.使用方法网上很多,这里教大家一个超简单安装h ...