【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命令行,更好地完成各种复杂的数据处理任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/586470.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Peter算法小课堂—浮点数危机

大家先想想下面这个代码运行结果&#xff1a; #include <bits/stdc.h> using namespace std; int main(){double x5.2;double y4.11.1;cout<<(x<y)<<endl;cout<<x-y<<endl;return 0; } 最终发现&#xff0c; &#xff1f;&#xff1f;&…

Unity之ShaderGraph如何实现瓶装水效果

前言 有一个场景在做效果时,有一个水瓶放到桌子上的设定,但是模型只做了个水瓶,里面是空的,所以我就想办法,如何做出来瓶中液体的效果,最好是能跟随瓶子有液体流动的效果。 如下图所示: 水面实现 水面效果 液体颜色设置 因为液体有边缘颜色和内里面颜色,所以要分开…

WEB渗透—PHP反序列化(十一)

Web渗透—PHP反序列化 课程学习分享&#xff08;课程非本人制作&#xff0c;仅提供学习分享&#xff09; 靶场下载地址&#xff1a;GitHub - mcc0624/php_ser_Class: php反序列化靶场课程&#xff0c;基于课程制作的靶场 课程地址&#xff1a;PHP反序列化漏洞学习_哔哩…

【力扣题解】P106-从中序与后序遍历序列构造二叉树-Java题解

&#x1f468;‍&#x1f4bb;博客主页&#xff1a;花无缺 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! 本文由 花无缺 原创 收录于专栏 【力扣题解】 文章目录 【力扣题解】P106-从中序与后序遍历序列构造二叉树-Java题解&#x1f30f;题目描述&#x1f4a1;题…

2024 通义语音 AI 技术图景,大模型引领 AI 再进化

自 1956 年达特茅斯会议上&#xff0c;约翰麦卡锡首次提出了“人工智能”这一术语。AI 在此后七十年的发展中呈现脉冲式趋势&#xff0c;每隔 5-10 年会出现一次技术革新和域定。在这一技术探索进程之中&#xff0c;预训练基础模型逐渐成为主流探索方向&#xff0c;受到学术界和…

C#下将点云数据保存为PLY格式

目前没有找到C#下将点云数据保存为PLY格式的库&#xff0c;查看了一下PLY格式&#xff0c;所以自己写了个方法实现点云数据保存PLY格式 public static string SavePointCloudToPLY(string No, float[] x, float[] y, float[] z){ string result "";Task.Run(() >…

基本运算器实验静态随机存储器实验

1.1 基本运算器实验 1. 实验记录 ①运算结果 首先按照实验指导书进行连线&#xff0c;然后打开试验箱电源&#xff0c;把A&#xff0c;B两个数存到寄存器中&#xff0c;然后改变s3 s2 s1 s0 的值&#xff0c;产生脉冲&#xff0c;观察对应的数据总线上的值以及两个标志位。 …

机器学习分类模型

机器学习常见分类模型及特点 机器学习常见分类模型优缺点 决策树模型 决策树&#xff08;Decision Tree&#xff09;是一类常见的机器学习方法&#xff0c;可应用于分类与回归任务&#xff0c;这里主要讨论分类决策树。决策树是基于树结构来进行决策的。下图是使用决策树来决定…

分布式技术之分布式发布订阅通信

文章目录 什么是发布订阅&#xff1f;发布订阅的原理Kafka 发布订阅原理及工作机制 发布订阅的应用 什么是发布订阅&#xff1f; 发布订阅的三要素是生产者、消费者和消息中心&#xff0c;生产者负责产生数据放到消息中心&#xff0c;消费者向消息中心订阅自己感兴趣的消息&am…

【详解】KMP算法——每步配图让你打穿KMP

介绍 什么是KMP算法&#xff1a; KMP算法主要运用串的模式匹配中&#xff08;简单来说就是在s串中找到一个与t串相等的子串&#xff0c;称为模式匹配&#xff09;例如s为abcdef&#xff0c;t为bcd&#xff0c;那么就是在s中找到bcd&#xff0c;并返回其在s中的首下标&#xf…

(JAVA)-(网络编程)-初始网络编程

网络编程就是在通信协议下&#xff0c;不同的计算机上运行的程序&#xff0c;进行的数据传输。 讲的通俗一点&#xff0c;就是以前我们写的代码是单机版的&#xff0c;网络编程就是联机版的。 应用场景&#xff1a;即时通信&#xff0c;网游对战&#xff0c;金融证券&#xf…

arm day7

开关中断控制 main.c #include "key_it.h" #include "uart.h" void delay(int ms) {int i,j;for(i0;i<ms;i){for(j0;j<2000;j);} }int main() {key2_it_config();key1_it_config();key3_it_config();all_led_init();char buf[128];gets(buf); whil…

Android APK未签名提醒

最近新建了一个项目&#xff0c;在build.gradle中配置好了签名&#xff0c;在执行打包的时候打出的包显示已签名&#xff0c;但是在上传市场的时候提示未签名。于是排查了好久&#xff0c;发现在build.gradle中配置的minsdk 24&#xff0c;会导致不使用V1签名&#xff0c;于是我…

Kubernetes技术与架构-集群管理

Kubernetes技术与架构提供支撑工具支持集群的规划、安装、创建以及管理。 数字证书 用户可以使用easyrsa、openssl、cfssl工具生成数字证书&#xff0c;在kubernetes集群的api server中部署数字证书用于访问鉴权 资源管理 如上所示&#xff0c;定义一个服务类service用于负…

iptables防火墙(二)

目录 1、SNAT策略及应用 1.1、SNAT 策略概述 1.2、SNAT 策略的应用 2、DNAT 策略及应用 2.1、DNAT 策略概述 2.2、DNAT 策略的应用 3、规则的导出、导入 3.1、规则的备份及还原 3.2、使用 iptables 服务 4、使用防火墙脚本 4.1、防火墙脚本的构成 &#xf…

Python新姿势:用魔法方法玩转对象

文章目录 前言1\. 对象构建2\. 对象属性访问3\. 对象比较4\. 对象输出5\. 对象运算6\. 总结Python技术资源分享1、Python所有方向的学习路线2、学习软件3、入门学习视频4、实战案例5、清华编程大佬出品《漫画看学Python》6、Python副业兼职与全职路线 前言 Python中魔法方法&a…

百兆集成RJ45连接器电路设计原理

华强盛电子导读&#xff1a;HR911105A-H1159A01A-GY百兆网口带变压器原理 百兆集成RJ45连接器电路设计原理涉及到网络通信和电子工程领域。RJ45连接器是一种常见的网络连接器&#xff0c;广泛应用于以太网和其他网络通信中。 以下是百兆集成RJ45连接器电路设计的基本原理&…

冠赢互娱基于 OpenKrusieGame 实现游戏云原生架构升级

作者&#xff1a;力铭 关于冠赢互娱 冠赢互娱是一家集手游、网游、VR 游戏等研发、发行于一体的游戏公司&#xff0c;旗下官方正版授权的传奇类手游——《仙境传奇》系列深受广大玩家们的喜爱。基于多年 MMORPG 类型游戏的自研与运营经验&#xff0c;冠赢互娱正式推出了 2D M…

【数据结构】快速排序(4种方式实现)

前言&#xff1a;前面我们学习了几种相对比较简单的排序&#xff0c;今天我们要一起学习的是快速排序&#xff0c;我们将通过四种方式来模拟实现快排。 &#x1f496; 博主CSDN主页:卫卫卫的个人主页 &#x1f49e; &#x1f449; 专栏分类:数据结构 &#x1f448; &#x1f4a…

OpenCV(Python)基础—9小时入门版

OpenCV(Python)基础—9小时入门版 # # Author : Mikigo # Time : 2021/12/1 # 一、一句话简介 OpenCV (Open Source Computer Vision Library) 是用 C 语言编写&#xff0c;提供 Python、Java 等语言 API的一个开源计算机视觉库。 二、安装 1、Debian 系使用 apt 安装 O…