Linux学习笔记24——进程管道
一 管道的作用
通常把一个进程的输出通过管道连接到另一个进程的输入。
二 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——进程管道的更多相关文章
- Linux学习笔记(六) 进程管理
1.进程基础 当输入一个命令时,shell 会同时启动一个进程,这种任务与进程分离的方式是 Linux 系统上重要的概念 每个执行的任务都称为进程,在每个进程启动时,系统都会给它指定一个唯一的 ID, ...
- Linux学习笔记25——命名管道(FIFO)
1 命名管道(FIFO) 管道应用的一个重大缺陷就是没有名字,因此只能用于亲缘进程之间的通信.后来从管道为基础提出命名管道(named pipe,FIFO)的概念,该限制得到了克服.FIFO不同于管道 ...
- linux学习笔记之进程
一.基础知识 1:进程. 1,进程ID: 非负整数,具有唯一性. 1)ID=0的进程:调度进程/交换进程.内核的一部分.不执行任何磁盘上的程序. 2)ID=1的进程:init进程. 1-自举结束时,由 ...
- linux学习笔记-13.进程控制
1.查看用户最近登录情况 lastlastlog 2.查看硬盘使用情况 df 3.查看文件大小 du 4.查看内存使用情况 free 5.查看文件系统 /proc 6.查看日志 ls /var/log ...
- Linux学习笔记(七) 查询系统
1.查看命令 (1)man 可以使用 man 命令名称 命令查看某个命令的详细用法,其显示的内容如下: NAME:命令名称 SYNOPSIS:语法 DESCRIPTION:说明 OPTIONS:选项 ...
- Linux学习笔记(一) 文件系统
对于每一个 Linux 学习者来说,了解 Linux 文件系统的结构是十分有必要的 因为在 Linux 中一切皆文件,可以说只有深入了解 Linux 的文件系统,才会对 Linux 有更深刻的理解 L ...
- Linux学习笔记(二) 文件管理
了解 Linux 系统基本的文件管理命令可以帮助我们更好的使用 Linux 系统,以下介绍几个常用的文件管理命令 1.pwd pwd 是 Print Working Directory 的简写,用于显 ...
- Linux学习笔记(四) vi编辑器
一.vi 编辑器 vi 编辑器 (Visual Interface) 是所有 Unix 及 Linux 系统下标准的编辑器,相当于 Windows 系统中的记事本 它有三种模式,分别是: Comman ...
- Linux学习笔记(五) 账号管理
1.用户与组账号 用户账号:包括实际人员和逻辑性对象(例如应用程序执行特定工作的账号) 每一个用户账号包含一个唯一的用户 ID 和组 ID 标准用户是系统安装过程中自动创建的用户账号,其中除 root ...
随机推荐
- WisDom.Net 框架设计(四) 用户安全
WisDom.Net ----用户安全 1.用户单机登录 正如其名这里要求其实就是显示用户只能在一台电脑上登录.防止多处登录,这里简单的说一下实现原理,我们在这里使用session +cookie ...
- 在github上搭建博客(使用Jekyll)
简单说,只需要三步,就可以在 Github 搭建起一个博客: 在 Github 上建一个名为 xxx.github.io 的库: 把看中了的 Jekyll 模板 clone 到本地: 把这个模板 pu ...
- Java环境变量配置&解决版本不一致问题
之前用Myeclipse编译运行Java没有问题 但是突然想用简单点的NotePad++以及cmd直接编译运行Java 这就让我倒腾了一晚上 先说下问题的解决,再总结下查阅的一些知识. 1.进行win ...
- 24种设计模式--装饰模式【Decorator Pattern】
装饰模式在中国使用的那实在是多,中国的文化是中庸文化,说话或做事情都不能太直接,需要有技巧的,比如说话吧,你要批评一个人,你不能一上来就说你这个做的不对,那个做的不对,你要先肯定他的成绩,表扬一下优点 ...
- android入门到熟练(一)
1.andro系统架构:Linux内核层(提供驱动),系统运行库层和android运行时库(提供C/C++库的主要特性,如SQLite,OpenGL,Webkit等和Dalvik虚拟机),应用框架层, ...
- SQL70001: This statement is not recognized in this context.
关于错误: SQL70001: This statement is not recognized in this context. 的产生原因以及解决办法. 在SQL Server Databas ...
- js 删除数组方法
今天遇到一个比较脑残的问题 ,在在用js删除数组的时候 delete 数组[下标]的方法删除数组时,该数组的下标变为null,但是数组的长度并没有发生相应的变化 转而使用splice(小标,第N个)删 ...
- Day19 Django之Form表单验证、CSRF、Cookie、Session和Model操作
一.Form表单验证 用于做用户提交数据的验证1.自定义规则 a.自定义规则(类,字段名==html中的name值)b.数据提交-规则进行匹配代码如下: """day19 ...
- bzoj 3041: 水叮当的舞步 迭代加深搜索 && NOIP RP++
3041: 水叮当的舞步 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 72 Solved: 44[Submit][Status] Descript ...
- hustoj 1017 - Exact cover dancing link
1017 - Exact cover Time Limit: 15s Memory Limit: 128MB Special Judge Submissions: 5851 Solved: 3092 ...