当前位置: 首页 > news >正文

【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**: BASHPIDBASHPID的优先级低于子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…...

安全生产知识竞赛活动方案

为进一步普及安全生产法律法规知识,增强安全意识,提高安全技能,经研究,决定举办以“加强安全法治、保障安全生产”为主题的新修订《安全生产法》知识竞赛活动,现将有关事项通知如下: 一、活动时间&#xf…...

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…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

HTML 列表、表格、表单

1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...

网站指纹识别

网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

初探Service服务发现机制

1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源&#xf…...

Selenium常用函数介绍

目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...