linux进程间通信:shell管道 | 的实现
文章目录
- 介绍
- 重定向函数介绍
- 总结
linux terminal输入如下命令,其中"|"符号即为我们上文中所说的无名管道

介绍
正如我们上文中所描述的"|“无名管道提供了具有亲缘关系的进程之间的通信,它由于直接使用系统调用,运行效率较高。则linux系统下可以大批量的使用”|"来提供命令直接输入输出的重定向。
具体shell中管道的实现可以参考如下图:
当我们直接执行lsmod时,此时进程文件描述符默认会打开标准输入,标准输出,标准错误三个文件。lsmod的输出内容会写到标准输出设备,即linux terminal显示屏。当我们加入了管道,其最终将标准输出重定向到管道的f[1]写描述符。
具体流程如下:
a. 将命令封装成进程:通过fork/exec系统调用
b. 该进程此时会默认打开stdin 0 ,stdout 1 ,sdterr 2 连接到终端上
c. 运行的命令从键盘读取数据并且把输出和错误消息写到屏幕上(标准输出一般默认是屏幕)
d. 通过重定向,可以从指定文件读取数据,或将数据输出到指定文件
e. 重定向IO的功能是由shell本身实现,标准流与文件连接
f. 程序本身并不知道数据最后流向哪里,他只知道将自身输出写到标准输出中
g. 通过命令:cmd > file 告诉shell将stdout定位到的文件file,于是shell就将文件描述符与指定的文件连接起来,程序将输出放入file而不是默认的屏幕
重定向函数介绍
如下三个函数
#include <unistd.h>
int dup(int oldfd); //将old文件描述符重定向给返回值
int dup2(int oldfd, int newfd); //重定向成功,则返回重定向后新的文件句柄#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Obtain O_* constant definitions */
#include <unistd.h>
int dup3(int oldfd, int newfd, int flags);
以上dup,dup2,dup3函数在shell中实现了将输入输出设备和管道联系了起来,将输入输出重定向到具体文件之中
int dup(int oldfd)
其中dup函数实现了将旧的文件描述符拷贝给新的文件描述符,此时old_fd和new_fd将会共享同一个文件的状态标记(读写权限等),文件偏移地址等#include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h>int main() {int fd,new_fd;//打开文件fd = open("write.txt",O_RDWR | O_CREAT,777);if(fd == -1){perror("open failed");exit (-1);}//将fd文件描述符拷贝到新的文件描述符,两个文件描述符共享同一个文件new_fd = dup(fd);write(fd, "hello",strlen("hello"));write(new_fd, "world", strlen("world"));write(fd, "zhang", strlen("world"));//紧接着new_fd对文件写操作之后的偏移地址进行写close(fd);close(new_fd);return 0; }
如果我们将以上中
new_fd
置为1(1的文件句柄代表标准输出),则write的结果将输出到屏幕
如下代码:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h>int main() {int new_fd;new_fd = dup(1); //将new_fd重定向到标准输出,即copy一个标准输出到new_fdwrite(1,"hello",strlen("hello"));write(new_fd,"world\n",strlen("wrold\n")); //此时操作系统为该进程文件重新分配一个文件句柄3,因为0,1,2已经被占用//printf("new_fd = %d\n",new_fd);close(new_fd);return 0; }
int dup2(int old_fd,int new_fd)
dup2
函数和dup
函数可以指定 我们想要重定向到的文件句柄,比如我们想将标准输出重定向到指定的文件
查看如下代码:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h>int main() {int fd,new_fd;char *ptr = "hello world\n";fd = open("data.log",O_RDWR | O_CREAT,664);if (fd == 0) {perror("open failed");exit(-1);}new_fd = dup2(fd,1); //将标准输出重定向到fd文件句柄,即data.log文件if (new_fd == -1) {perror("open failed ");exit(-1);}printf("fd : %d \n new_fd :%d\n",fd,new_fd); //同样是标准输出,那么它的输出也会输出到 fd文件句柄。同时对new_fd的操作即为对标准输出的操作write(1,ptr,strlen(ptr));write(new_fd,"i am new\n",strlen("i am new\n"));//向new_fd中写入,即向标准输出中写入,但是此时标准输出已经重定向到了data.log中close(fd);return 0; }
输出如下:
此时这个输出很有意思,可以发现c语言的面向过程式有点不太对,为什么write(" i am new")
是在printf
之后调用,但是它的输出结果确是在prinf
前输出呢?这里很明显,printf
函数的同样是标准输出,但是它是在程序执行完成之后将结果重定向到标准输出的,而我们调用write(“i am new”)确是已经在运行过程中将结果通过标准输出重定向到文件,所以此时printf的输出会晚于用重定向函数的结果[root@node1 /]# cat data.log hello world i am new fd : 3 new_fd :1
通过管道以及重定向实现如下操作
lsmod |grep snd
基本流程如下
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <fcntl.h>int main() {int pipe_fd [2]; if (pipe(pipe_fd) == -1) {//创建一个管道perror("pipe");exit (-1);} else {int ret;ret = fork();if (ret == 0) { //标准输出重定向到管道的写端,即lsmod的输出将重定向到f[1]dup2(pipe_fd[1],1);execlp("lsmod","lsmod",NULL,NULL);}else {dup2(pipe_fd[0],0); //从f[0]读出f[1]写入的内容到标准输入close(pipe_fd[1]); execlp("grep","grep","snd",NULL);}}return 0; }
总结
通过以上探讨,我们了解了linux shell中管道以及重定向符的实现原理,通过dup系列函数对进程文件句柄的复制实现。有意思~
相关文章:

Golang的接口
当一只鸟走路像鸭子,游泳像鸭子,叫起来也像鸭子,那么我们就认为它就是鸭子。 Duck typing 的理念因此比喻得名。 Golang 通过 interface 实现 duck typing。 Effective Go 文章中这样描述 interface: interface 指定了一种描述对象行为的方法…

mysql 5.6.15_mysql-5.6.15-win32.zip免安装配置
此随笔是根据网上的资料整理的:环境:Windows XP系统软件来源:mysql官网下载1.下载mysql-5.6.15-win32.zip;2.解压MySQL压缩包;以下以加压到“F:\Program Files\Mysql\mysql-5.6.15-win32”为例:3.将解压目录…

jquery treeview 树形插件
jquery treeview 插件参数说明 treeview开源地址:https://github.com/jzaefferer/jquery-treeview 1、animated:String or Number 设置展开子节点时的显示速度,有 slow、normal、fast 或者指定速度值,与 jQuery 的 hide࿰…

spark调优(一)-开发调优,数据倾斜,shuffle调优
主要分为开发调优、资源调优、数据倾斜调优、shuffle调优几个部分。 开发调优和资源调优是所有Spark作业都需要注意和遵循的一些基本原则,是高性能Spark作业的基础;数据倾斜调优,主要讲解了一套完整的用来解决Spark作业数据倾斜的解决方案&am…

linux进程间通信:popen函数通过管道与shell通信
函数描述 FILE *popen(const char* command,const char* type) 该函数的执行过程如下: a. 调用pipe创建一个管道,并fork创建一个子进程来执行shell,shell会创建一个子进程来执行commad b. 将父进程的输入输出重定向到管道,建立一个单向的数据…

新的小游戏发布啦。Pop Jungle
丛林爱消除是一款画面清新,效果绚丽的消除类休闲游戏。你只需要选中尽可能多的图块,并消除它们就可以得到高分,并有无限多的关卡等待你去征服。一旦你开始玩儿你将无法停止下来,如果你还是消除星星的粉丝,那你更加不能…

mysql thread safe_Windows环境下完全手工配置Apache、MySQL和PHP(Thread Safe)
happydagui:现在LAMP(Linux、Apache、MySQL、PHP/Perl/Python的简称)已经很流行了。在Windows下也有类似的,比如 WAMP(Apache, MySQL, PHP on Windows)。这篇文章主要是介绍如何在Windows环境下完全手工配置Apache、MySQL和PHP,都是解压后直接…

点滴积累【C#】---检验编号在本表中自动生成,与其他表无关
检验编号在本表中自动生成,与其他表无关 效果: 描述:在本表中自动生成编号,与其他表无关。 调用: 1 protected void Page_Load(object sender, EventArgs e)2 {3 Response.Expires -1;4 …

Alpha冲刺(9/10)
团队信息 队名:爸爸饿了组长博客:here作业博客:here组员情况 组员1(组长):王彬 过去两天完成了哪些任务 学习jQuery的AJAX部分的基础知识,对web端如何异步获取服务器信息有了初步认识接下来的计划 & 还…

linux进程通信:pipe实现进程同步
文章目录通过管道同步进程实现代码管道缓冲区设置缓冲区大小总结 :pipe的特点通过管道同步进程 管道自带同步互斥机制: 管道的内核实现:fs/pipe.c ,主要通过内核的锁以及等待队列等机制实现 管道的write操作会阻塞进程 当内存缓冲…

(转)MySQL联表查询
资料源于网络 一.内联结、外联结、左联结、右联结的含义及区别在SQL标准中规划的(Join)联结大致分为下面四种:1.内联结:将两个表中存在联结关系的字段符合联结关系的那些记录形成记录集的联结。2.外联结:分为外左联结和…

极小连通子图和极大连通子图_强连通分量与拓扑排序
前言由于GacUI里面开始多处用上拓扑排序,我决定把之前瞎JB搞出来的算法换掉,换成个正式的。之前我自己弄了个写起来很简单的算法,然后每一处需要用到的地方我就重新做一遍。当然这样肯定也是不行的,我觉得也差不多积累到重构的临界…

INTERVAL数据类型-007学习笔记
http://baggio785.itpub.net/post/31233/286119 INTERVAL数据类型用来存储两个时间戳之间的时间间隔。 可以指定years and months,或者days,hours,minuts,seconds之间的间隔。本文为oracle的学习笔记,结合实例介绍INTERVAL数据类型。 INTERVAL数据类型用…

scrapy模拟用户登录
scrapy框架编写模拟用户登录的三种方式: 方式一:携带cookie登录,携带cookie一般请求的url为登录后的页面,获取cookie信息应在登录后的页面获取,cookie参数应转成字典形式 # -*- coding: utf-8 -*- import re import sc…

linux 系统调用 open函数使用
函数介绍 本文仅仅将open系统调用的使用简单总结一下,关于其实现原理大批的大佬分享可以自行学习。open系统调用主要用于打开或者创建一个文件,并返回文件描述符。 头文件 #include <fcntl.h>函数名称 a. int open(const char *pathname, int fl…

配置zendframework开始工作(加入环境变量)
首先需要把把两个路径加入到环境变量中 1、我用的php环境是xampp,安装在di盘,我要把d:/xampp/php/这个路径加入到环境变量 2、下载zendframework(我用的版本是1.),把安装包中的bin目录加入到环境变量 3、关于设置php/php.ini中设置…

mysql计算两gps坐标的距离_mysql 计算两坐标间的距离
mysql 5.6.1 加入了空间数据支持功能,新增了st_*相关函数,可以非常方便的计算两个地理坐标点的距离了。如下例子:按我的坐标计算周边坐标的距离并由近到远排序select name,st_distance(point(113.327955,23.129717),point)*111195 as distanc…

(转)mxArray数据类型
1 、数据类型mxArray的操作 在上节的Matlab引擎函数中,所有与变量有关的数据类型都是mxArray类型。数据结构mxArray以及大量的mx开头的函数,广泛用于Matlab 引擎程序和Matlab C数学库中。mxArray是一种很复杂的数据结构,与Matlab中的array相对…

Bootstrap笔记(记录不会的知识)
head: <link rel"stylesheet" href"bootstrap.min.css" /> 引入bootstrap.min.css文件 <meta name"viewport" content"widthdevice-width,initial-scale1" /> content"widthdevice-width:设为…

linux 系统调用 read,write和lseek 使用
read系统调用 头文件 #include <unistd.h>函数使用 ssize_t read(int fd, void *buf, size_t count) read 函数会从文件描述符fd中读取指定的count长度的内容,并且将读到的结果放入到buf缓冲区中返回值 count 读取成功,则会返回读到的字节数 小于…

简单有趣的matlab小程序_超实用有趣的五个小程序推荐
大家好,我是小胖。废话不多说,进入正题。1.一周CP共读有趣的灵魂总会相遇。一个极简的社交小程序。通过选择自己喜欢的一本书,匹配到那个跟自己有着一样有趣灵魂的TA。选择好要阅读哪本书之后,填写下资料,就能在看一本…

一些linux下的性能监测工具
1.gprof http://blog.csdn.net/stanjiang2010/article/details/5655143 2.系统性能调优 http://www.ibm.com/developerworks/cn/linux/l-time/part2/index.html?cadrs perf http://www.ibm.com/developerworks/cn/linux/l-cn-perf1/ oprofile http://www.ibm.com/developerwor…

uva 10183 How many Fibs?
数学题: 给你一个区间[a,b]在该区间内有多少个费波那列数(包括a,b),数据规模达到10^100。 这题的原理很简单,基本没什么算法,其实更偏重于编程能力,需要用到高精度。另外找区间的地方…

2018/11/29 一个64位操作系统的设计与实现 02 (安装nasm)
操作系统: Centos7 在nasm官网上的到通过yum安装nasm的方法 首先在/etc/yum.repos.d/目录下 新建一个名为nasm.repo的文件, 在这么文件中写入内容如下 : [nasm] nameThe Netwide Assembler baseurlhttp://www.nasm.us/pub/nasm/stable/linux/ enabled1 gpgcheck0[nasm-testing]…

a-awk 计算数值最大,最小,平均值并保留指定位数
awk 计算最大值 echo -e "1\n2\n3\n10\n9\n5\n11\n"|awk BEGIN {max 0} {if ($1>max) max$1 } END {print "Max", max} 输出为:Max 11 或者可以使用sort命令更为便捷: cho -e "1\n2\n3\n10\n9\n5\n11\n"|sort -n |tai…

第18章:MYSQL分区
第18章:分区 目录 18.1. MySQL中的分区概述18.2. 分区类型18.2.1. RANGE分区18.2.2. LIST分区18.2.3. HASH分区18.2.4. KEY分区18.2.5. 子分区18.2.6. MySQL分区处理NULL值的方式18.3. 分区管理18.3.1. RANGE和LIST分区的管理18.3.2. HASH和KEY分区的管理18.3.3. 分…

mysql属性配置提高查询_MYSQL性能优化-安装时优化参数配置提高服务性能
MYSQL性能优化一直是个头痛的问题,目前大多都是直接把页面html静态页面或直接使用了缓存技术,下面我就mysql本身的性能优化来分享一下。安装时优化参数配置提高服务性能在Linux下安装Mysql采用默认配置安装的Mysql却未必是工作在最佳性能状态的ÿ…

c++引用的自我见解
2019独角兽企业重金招聘Python工程师标准>>> 刚开始学习c 学完指针后,其细节比较好明白,但学到引用了以后,只知其表却不知其底层的实现机制,虽然知道引用是别名、声明必须同时初始化等等,但这只是概念性的东…

c# yield关键字原理
https://www.cnblogs.com/blueberryzzz/p/8678700.html c# yield关键字原理详解 1.yield实现的功能yield return:先看下面的代码,通过yield return实现了类似用foreach遍历数组的功能,说明yield return也是用来实现迭代器的功能的。 using st…

linux进程间通信:命名管道FIFO
文章目录FIFO 通信特点系统调用接口应用拥有亲缘关系之间的进程通信非亲缘关系进程之间的通信总结FIFO 通信特点 FIFO文件有文件名 可以像普通文件一样存储在文件系统之中可以像普通文件一样使用open/write读写和pipe文件一样属于流式文件,不…