【linux】Linux管道的原理与使用场景
Linux管道是Linux命令行界面中一种强大的工具,它允许用户将多个命令链接起来,使得一个命令的输出可以作为另一个命令的输入。这种机制使得我们可以创建复杂的命令链,并在处理数据时提供了极大的灵活性。在本文中,我们将详细介绍Linux管道的使用方法和实际应用。

管道的基本概念
管道(pipe)是一种特殊的文件类型,它在内存中创建一个缓冲区,用于存储一种命令的输出和另一种命令的输入。
管道的创建和使用非常简单,只需要使用|符号即可。
例如,我们可以使用ll命令列出当前目录中的所有文件,然后通过管道将这些文件的列表传递给grep命令,以搜索某个特定的文件:
$ ll | grep ooxx
-rw-rw-r-- 1 vagrant vagrant    7 Dec 21 06:07 ooxx.txt
 
在这个例子中,ls命令的输出成为了grep命令的输入,这就是管道的基本用法。
管道的工作原理
管道背后的主要思想是“生产者-消费者”模型,其中一个进程产生数据,而另一个进程消费这些数据。
创建管道的系统调用是pipe(),它创建了一对文件描述符:一个用于读,一个用于写。当在shell中使用管道时,shell会自动调用pipe()以及其他一些系统调用来设置进程间的数据流。
以下是管道创建和数据流动的基本步骤:
-  
创建管道:当用户在shell中输入一个包含管道的命令(如
cmd1 | cmd2)时,shell会使用pipe()系统调用创建一个管道。pipe()系统调用返回两个文件描述符:一个用于管道的读端,一个用于管道的写端。 -  
创建进程:接下来,shell使用
fork()系统调用创建两个子进程。每个子进程将执行命令链中的一个命令(cmd1和cmd2)。 -  
设置文件描述符:在执行命令之前,shell会对子进程的文件描述符进行操作,确保cmd1的标准输出(stdout)连接到管道的写端,而cmd2的标准输入(stdin)连接到管道的读端。这通常通过 dup2() 或 close() 系统调用来完成。
 -  
执行命令:然后,shell使用
exec()系统调用来替换子进程的内存空间,运行相应的命令。cmd1 进程写入数据到管道的写端,而 cmd2 进程从管道的读端读取数据。 -  
数据流动:当 cmd1 进程向管道写入数据时,这些数据被缓存在内核中,直到 cmd2 进程从管道读取它们。
如果管道的写端没有数据可写,cmd2 进程在尝试读取时会阻塞(等待),直到有数据可读。
如果管道的读端没有进程读取数据,cmd1 进程在写入时会收到一个 SIGPIPE 信号,通常会导致写入进程终止。 -  
清理:当两个命令都执行完毕后,shell会关闭所有打开的文件描述符,并回收子进程的资源。
 
通过这种方式,管道能够将不同命令的输出和输入无缝连接起来,创建一个数据处理的流水线,极大地增强了shell脚本和命令行的功能性和灵活性。
管道产生进程的演示
查看当前bash的PID:
$ echo $$
2514
 
使用管道连接下面的两个命令:
$  { echo $BASHPID; read a; } | { cat; read b; }
5610
 
我们发现5610的进程阻塞住了,在等待输入。
查看父进程生成的两个子进程的PID:
$ ps -ef|grep 2514
vagrant   5610  2514  0 08:07 pts/0    00:00:00 -bash
vagrant   5611  2514  0 08:07 pts/0    00:00:00 -bash
 
两个子进场的PID分别为5610(第一个命令)和5611(第二个命令)。
再来看看管道是怎么将两个进程的输入和输出连接在一起的:
5610(第一个命令)的文件描述符目录如下:
$ ll /proc/5610/fd
lrwx------ 1 vagrant vagrant 64 Dec 26 08:08 0 -> /dev/pts/0
l-wx------ 1 vagrant vagrant 64 Dec 26 08:08 1 -> 'pipe:[103565]'
lrwx------ 1 vagrant vagrant 64 Dec 26 08:08 2 -> /dev/pts/0
 
5610(第一个命令)的输出流连接到管道pipe:[103565]上。
5611(第二个命令)的文件描述符目录如下:
$ ll /proc/5611/fd
lr-x------ 1 vagrant vagrant 64 Dec 26 08:08 0 -> 'pipe:[103565]'
lrwx------ 1 vagrant vagrant 64 Dec 26 08:08 1 -> /dev/pts/0
lrwx------ 1 vagrant vagrant 64 Dec 26 08:08 2 -> /dev/pts/0
 
5611(第二个命令)的输入流连接到管道pipe:[103565]上,这样就将两个进程的输入和输出连接在一起了。
$ 和 和 和BASHPID的区别
在上面的例子中,我们演示了$$和$BASHPID这两个变量都能获取当前进程的ID(PID),那么他们直接有什么区别呢?
先将上面管道的的例子中的$BASHPID替换为$$执行:
$ { echo $$; read a; } | { cat; read b; }
2514
 
发现打印的是父进程的PID(2514),而不是子进程的PID,这是为什么呢?
$ 和 和 和BASHPID的区别:
-  
$$:$$的优先级高于子shell(在脚本中通过括号创建的子shell(command)或者在管道中
|),在执行命令的时候会先将$$替换为父进程的PID(2514),再创建子进程执行shell。 -  
** B A S H P I D ∗ ∗ : BASHPID**: BASHPID∗∗:BASHPID的优先级低于子shell,所以在执行命令的时候会先创建子进程,然后在执行命令,这样打印的就是子进程的PID。
 
下面是一个例子来展示它们之间的区别
下面的例子也是同样的道理:
$ echo "PID of the current shell: $$"
PID of the current shell: 2514$ echo "BASHPID of the current shell: $BASHPID"
BASHPID of the current shell: 2514$ ( echo "PID of the subshell: $$"; echo "BASHPID of the subshell: $BASHPID" )
PID of the subshell: 2514
BASHPID of the subshell: 6050
 
在不涉及子shell的情况下,$ 和 和 和BASHPID通常会返回相同的值,因为当前Bash实例就是当前shell。但是在涉及子shell的复杂脚本中,理解这两个变量之间的区别非常重要,以便正确地获取所需的PID。
管道的效率与限制
以下是管道的效率特点:
-  
内核级操作:管道的数据传输是在内核空间进行的,没有涉及用户空间和内核空间之间的数据拷贝,这使得管道非常高效。
 -  
无需临时文件:管道允许直接在进程间传递数据,不需要写入到临时文件中再读取,减少了磁盘I/O操作,提高了数据处理速度。
 -  
并发执行:管道连接的命令可以同时执行,不需要等待前一个命令完成后才开始下一个命令,这样可以更充分地利用CPU资源。
 -  
缓冲机制:管道本身具有一定的缓冲区,这可以减少读写操作的次数,提高效率。
 
以下是管道的限制:
-  
单向数据流:管道是单向的,数据只能从管道的一端流向另一端。如果需要双向通信,则需要使用两个管道或其他通信机制,如套接字。
 -  
固定大小的缓冲区:管道的缓冲区大小是固定的,通常取决于系统内核。一旦缓冲区满了,写操作就会阻塞,直到有进程读取数据为止。同样,如果缓冲区为空,读操作也会阻塞。
 -  
数据完整性:管道不保证消息边界,如果需要传递结构化的数据,发送和接收进程需要约定数据格式或使用特定的协议来确保数据的完整性。
 -  
阻塞问题:如果管道的读端没有进程读取数据,写端的进程在写入数据时将会收到 SIGPIPE 信号。如果管道的写端没有进程写入数据,读端的进程会读取到文件结束符(EOF),这可能导致进程阻塞或终止。
 -  
资源限制:每个用户和系统都有打开文件描述符的数量限制,大量使用管道可能会耗尽可用的文件描述符。
 -  
错误处理:管道中的错误可能不会直接传递给前一个命令。例如,如果 cmd1 | cmd2 中的 cmd2 失败了,cmd1 可能仍然在不知情的情况下继续运行,除非它试图写入更多数据到已经因为 cmd2 的终止而关闭的管道。
 
管道的实际应用
Linux管道在实际应用中非常广泛,可以用于各种数据处理和工作流程的构建。以下是一些常见的应用场景和例子:
-  
文本处理和过滤器:管道非常适合处理文本数据。可以使用各种文本过滤器(如grep、sed、awk等)组合起来进行文本搜索、替换、提取等操作。例如,可以通过将ls命令的输出传递给grep来搜索特定的文件:
ls | grep .txt。 -  
数据转换和格式化:可以使用管道将一个命令的输出传递给另一个命令进行数据转换和格式化。例如,可以使用cat命令将一个文件的内容输出到管道,然后使用tr命令将其中的大写字母转换为小写字母:
cat file.txt | tr 'A-Z' 'a-z'。 -  
进程监控和管理:可以使用管道来监控和管理系统中的进程。例如,可以使用ps命令获取进程列表,并将其传递给grep命令来筛选特定的进程:
ps aux | grep nginx。 -  
多命令串联:可以使用管道将多个命令串联在一起,形成更复杂的工作流程。例如,可以使用find命令查找特定类型的文件,并将结果传递给xargs命令来执行后续的操作:
find . -name "*.txt" | xargs rm。 -  
日志分析和处理:管道可以用于实时分析和处理日志数据。例如,可以使用tail命令实时监视日志文件,并将其输出传递给grep命令来筛选感兴趣的日志条目:tail -f logfile.txt | grep “error”。
 -  
数据流分析和统计:可以使用管道将数据流传递给统计命令进行数据分析和统计。例如,可以使用cat命令将一个文件的内容输出到管道,然后使用wc命令统计行数、单词数和字符数:
cat file.txt | wc。 
这只是一小部分管道的应用场景和例子,实际上,几乎任何需要将多个命令或工具组合起来进行数据处理和操作的情况下,都可以考虑使用管道。通过灵活地组合各种命令和工具,可以构建出强大而高效的数据处理流程。
结语
总的来说,Linux管道是一个非常强大的工具,它可以帮助我们在处理数据时提供极大的灵活性。通过学习和掌握管道的使用,我们可以更有效地使用Linux命令行,更好地完成各种复杂的数据处理任务。
相关文章:
【linux】Linux管道的原理与使用场景
Linux管道是Linux命令行界面中一种强大的工具,它允许用户将多个命令链接起来,使得一个命令的输出可以作为另一个命令的输入。这种机制使得我们可以创建复杂的命令链,并在处理数据时提供了极大的灵活性。在本文中,我们将详细介绍Li…...
nvidia jetson xavier nx developer kit version emmc版重装系统
一、将开发板上的外置硬盘取下来格式化 二、在双系统ubuntu安装SDK Manager(.deb文件) SDK Manager | NVIDIA Developer sudo apt install ./sdkmanager_1.9.2-10884_amd64.deb 报错直接百度错误,执行相应命令即可 三、 运行SDK Manager …...
命令模式-实例使用
未使用命令模式的UML 使用命令模式后的UML public abstract class Command {public abstract void execute(); }public class Invoker {private Command command;/*** 为功能键注入命令* param command*/public void setCommand(Command command) {this.command command;}/***…...
将网页变身移动应用:网址封装成App的完全指南
什么是网址封装? 网址封装是一个将你的网站或网页直接嵌入到一个原生应用容器中的过程。用户可以通过下载你的App来访问网站,而无需通过浏览器。这种方式不仅提升了用户体验,还可利用移动设备的功能,如推送通知和硬件集成。 小猪…...
探讨kernel32.dll文件是什么,有效解决kernel32.dll丢失
在使用电脑时,你是否遇到过kernel32.dll丢失的困扰?面对这个问题,我们需要及时去解决kernel32.dll丢失的问题。接下来,我们将深入探讨kernel32.dll的功能以及其在操作系统和应用程序中的具体应用领域,相信这将对你解决…...
LOAM: Lidar Odometry and Mapping in Real-time 论文阅读
论文链接 LOAM: Lidar Odometry and Mapping in Real-time 0. Abstract 提出了一种使用二维激光雷达在6自由度运动中的距离测量进行即时测距和建图的方法 距离测量是在不同的时间接收到的,并且运动估计中的误差可能导致生成的点云的错误配准 本文的方法在不需要高…...
如何使用Docker将.Net6项目部署到Linux服务器(三)
目录 四 安装nginx 4.1 官网下载nginx 4.2 下载解压安装nginx 4.3 进行configure 4.4 执行make 4.5 查看nginx是否安装成功 4.6 nginx的一些常用命令 4.6.1 启动nginx 4.6.2 通过命令查看nginx是否启动成功 4.6.3 关闭Nginx 4.6.5 重启Nginx 4.6.6 杀掉所有Nginx进程 4.…...
《Spring Cloud学习笔记:分布式事务Seata》
解决分布式事务的方案有很多,但实现起来都比较复杂,因此我们一般会使用开源的框架来解决分布式事务问题。 在众多的开源分布式事务框架中,功能最完善、使用最多的就是阿里巴巴在2019年开源的Seata了。 1. 初识Seata Seata是 2019 年 1 月…...
MySQL:权限控制
要授予用户帐户权限,可以用GRANT命令。有撤销用户的权限,可以用REVOKE命令。这里以 MySQl 为例,介绍权限控制实际应用。 GRANT授予权限语法: GRANT privilege,[privilege],.. ON privilege_level TO user [IDENTIFIED BY passwo…...
安全生产知识竞赛活动方案
为进一步普及安全生产法律法规知识,增强安全意识,提高安全技能,经研究,决定举办以“加强安全法治、保障安全生产”为主题的新修订《安全生产法》知识竞赛活动,现将有关事项通知如下: 一、活动时间…...
2023 IoTDB Summit:天谋科技 CTO 乔嘉林《IoTDB 企业版 V1.3: 时序数据管理一站式解决方案》...
12 月 3 日,2023 IoTDB 用户大会在北京成功举行,收获强烈反响。本次峰会汇集了超 20 位大咖嘉宾带来工业互联网行业、技术、应用方向的精彩议题,多位学术泰斗、企业代表、开发者,深度分享了工业物联网时序数据库 IoTDB 的技术创新…...
LangChain.js 实战系列:如何统计大模型使用的 token 使用量和花费
📝 LangChain.js 是一个快速开发大模型应用的框架,它提供了一系列强大的功能和工具,使得开发者能够更加高效地构建复杂的应用程序。LangChain.js 实战系列文章将介绍在实际项目中使用 LangChain.js 时的一些方法和技巧。 统计调用大模型的 to…...
基于多反应堆的高并发服务器【C/C++/Reactor】(中)EventLoop初始化
这个Dispatcher是一个事件分发模型,通过这个模型,就能够检测对应的文件描述符的事件的时候,可以使用epoll/poll/select,前面说过三选一。另外不管是哪一个底层的检测模型,它们都需要使用一个数据块,这个数据块就叫做DispatcherData。除此之外,还有另外一个部分,因为…...
OpenCV(Python)基础—9小时入门版
OpenCV(Python)基础—9小时入门版 # # Author : Mikigo # Time : 2021/12/1 # 一、一句话简介 OpenCV (Open Source Computer Vision Library) 是用 C 语言编写,提供 Python、Java 等语言 API的一个开源计算机视觉库。 二、安装 1、Debian 系使用 apt 安装 O…...
SpringBoot整合Canal
一 linux docker compose版本 1.第一步:基础环境 (1)第1步:安装jak、maven、git、nodejs、npm yum install maven mvn -v 安装maven时会帮安装jdkyum install git git --version 2.27.0yum in…...
用 Python 提取某一个公众号下的所有文章
当我们想要提取某一个公众号下的所有文章时,我们可以借助微信公众平台的开放接口,通过Python编写一个爬虫程序来实现。下面是一个示例代码,以及如何将其转化为一篇详细的微信公众号推文文章。 1. 导入所需库 首先,我们需要导入所…...
鸿蒙4.0实战教学—基础ArkTS(简易视频播放器)
构建主界面 主界面由视频轮播模块和多个视频列表模块组成,效果图如图: VideoData.ets中定义的视频轮播图数组SWIPER_VIDEOS和视频列表图片数组HORIZONTAL_VIDEOS。 // VideoData.ets import { HorizontalVideoItem } from ./HorizontalVideoItem; impo…...
4. 深入 Python 流程控制
 4. 深入 Python 流程控制 除了前面介绍的 while 语句,Python 还从其它语言借鉴了一些流程控制功能,并有所改变。 4.1. if 语句 也许最有名的是 if 语句。例如: >>> x int(raw_input("Please enter an integer: "))…...
2000-2022年上市公司股票流动性指标数据/股票流动性Amihud(原始数据+计算代码+计算结果)
2000-2022年上市公司股票流动性指标数据/股票流动性Amihud(原始数据计算代码计算结果) 1、时间:2000-2022年 3、指标:证券代码_没有单位、交易日期_没有单位、日个股交易金额_元、考虑现金红利再投资的日个股回报率_没有单位、交…...
Unity 数据存储PlayerPrefs管理类
Unity 数据存储PlayerPrefs管理类 Unity 数据存储PlayerPrefs管理类实现存取实体类对象存储格式为Json格式Singleton.csInventoryEntity.csDataManager.cs用法如下 Unity 数据存储PlayerPrefs管理类 实现存取实体类对象 存储格式为Json格式 源码如下: Singleton…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...
nnUNet V2修改网络——暴力替换网络为UNet++
更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...
