Linux系统编程-管道入门

晚上好,继续记录我的学习心得。

当你厌倦了自己的目标时,怎样继续保持专注?

误区:
成功人士说的都是自己如何“满怀热情”去努力实现他们的目标。不管是在商业、体育还是艺术界,我们听到的都是“一切都归结于激情”或者“你必须真的渴望得到它”之类的说法。

这让我们认为成功人士会有无限的激情,如果我们感到自己激情消退了,仿佛说明了我们不如他们,这让人很沮丧。

事实是:
他们没把话说完整。成功人士也会和普通人一样感到激情消退,这是任何人都无法逃脱的。熟能生巧。你练习的次数越多,它就变得越无聊,越像是机械地重复。

成功的最大威胁不是失败,而是倦怠
我们厌倦了好习惯,因为它们不再让我们开心。就好像写作一样,长期来看会给我带来好的结果,但是总会有那么几天我也会感觉写作是枯燥的。

成功人士更强大的地方在于:
尽管感到枯燥乏味,他们仍想办法坚持下去。

对抗枯燥感的小技巧:
在开始做自己不不想做的事情时: 先一边听音乐一边干,15分钟后再摘下耳机。必须控制时间,因为听得越多,音乐给你带来的满足感就会越少。

以下是正文,先明确一下正文的目的:

  • 举例说明 Linux 下父子进程如何使用管道进行通讯。

目录:

一、概述- 1. IPC 工具分类- 2. 什么是管道- 3. 管道的 2 个局限性- 4. 管道是最常用的 IPC- 5. 使用 pipe() 创建管道二、一个简单的例子 (simple_pipe.c)- 1. 代码分析- 2. 相关要点三、参考书籍四、欢迎加入我的微信群

一、概述

1. IPC 工具分类

  • 通信类 (communication):这类工具关注进程之间的数据交换。

  • 同步类 (synchronization):这类工具关注进程和线程操作之间的同步。

  • 信号类 (signal):尽管信号的主要作用并不在此,但在特定场景下仍然可以将它作为一种同步技术。更罕见的是信号还可以作为一种通信技术:信号编号本身是一种形式的信息,并且可以在实时信号上绑定数据。

2. 什么是管道

当从一个进程连接数据流到另一个进程时,我们使用术语管道 (pipe),也叫无名管道 (unnamed pipe)。通常是把一个进程的输出通过管道连接到另一个进程的输入。

管道是 UNIX 系统最古老的 IPC ,所有 UNIX 系统都提供这种通信机制。

3. 管道的 2 个局限性

  • 历史上,它是半双工的 (即数据只能在一个方向上流动)。现在,某些系统提供全双工管道,但是为了可移植性,我们不应预先假定系统支持全双工管道。

  • 管道只能在具有公共祖先的两个进程之间使用。通常,一个管道由一个进程创建,在进程调用 fork 之后,这个管道就能在父进程和子进程之间使用了。

4. 尽管有这 2 个局限性,半双工管道仍是最常用的 IPC

每当在管道中键入一个命令序列,让 shell 执行时,shell 都会为每一条命令单独创建一个进程,然后用管道将前一条命令进程的标准输出与后一条命令的标准输入相连接。shell 负责安排两个命令的标准输入和标准输出:

  • cmd1 的标准输入来自终端键盘;

  • cmd1 的标准输出传递给 cmd2,作为它的标准输入;

  • cmd2 的标准输出连接到终端屏幕;

shell 所做的工作实际上是对标准输入和标准输出流进行了重新连接,使数据流从键盘输入通过两个命令最终输出到屏幕上。

以 "$ ls | wc -l" 为例:

5. 使用 pipe() 创建管道

$ man 2 pipe
NAMEpipe, pipe2 - create pipe
SYNOPSIS#include <unistd.h>int pipe(int filedes[2]);

成功的 pipe() 调用会在数组 filedes 中返回两个打开的文件描述符:一个表示管道的读取端 (filedes[0]),另一个表示管道的写入端 (filedes[1])。

与所有文件描述符一样,可以使用 read() 和 write() 在管道上执行 I/O 操作。一旦向管道的写入端写入数据之后立即就能从管道的读取端读取数据。

二、一个简单的例子 (simple_pipe.c)

1. 代码分析

下面的程序演示了如何将管道用于父进程和子进程之间的通信:

int main(int argc, char *argv[])
{int pfd[2];char buf[BUF_SIZE];ssize_t numRead;if (argc != 2 || strcmp(argv[1], "--help") == 0)usageErr("%s string\n", argv[0]);if (pipe(pfd) == -1)    /* Create the pipe */errExit("pipe");switch (fork()) {case -1:errExit("fork");case 0:             /* Child  - reads from pipe */if (close(pfd[1]) == -1)            /* Write end is unused */errExit("close - child");for (;;) {              /* Read data from pipe, echo on stdout */numRead = read(pfd[0], buf, BUF_SIZE);if (numRead == -1)errExit("read");if (numRead == 0)break;                      /* End-of-file */if (write(STDOUT_FILENO, buf, numRead) != numRead)fatal("child - partial/failed write");}// cleanup...default:            /* Parent - writes to pipe */if (close(pfd[0]) == -1)            /* Read end is unused */errExit("close - parent");if (write(pfd[1], argv[1], strlen(argv[1])) != strlen(argv[1]))fatal("parent - partial/failed write");if (close(pfd[1]) == -1)            /* Child will see EOF */errExit("close");wait(NULL);                         /* Wait for child to finish */exit(EXIT_SUCCESS);}
}

运行效果:

$ ./simple_pipe 'msg from parent'
msg from parent

单个进程中的管道几乎没有任何用处。一般来讲都是使用管道让两个进程进行通信。为了让两个进程通过管道进行连接,在调用完 pipe() 之后可以调用 fork(),子进程会继承父进程的文件描述符的副本:

虽然父进程和子进程都可以从管道中读取和写入数据,但一般不这么使用管道。通常,在 fork() 之后,其中一个进程应该立即关闭管道的写入端的描述符,另一个则应该关闭读取端的描述符。在上面的例子中,父进程向子进程传输数据,所以它关闭了管道的读取端的描述符 filedes[0],而子进程则关闭管道的写入端的描述符 filedes[1]:


2. 相关要点

  1. 父子进程从同一个管道中读取和写入数据这种做法不好的原因是:

  • 如果两个进程同时试图从管道中读取数据,那么就无法确定哪个进程会首先读取成功——两个进程竞争数据了,即会产生竞争。

  • 使用管道进行双向通信更加简单的方法是:创建两个管道,在两个进程之间发送数据的两个方向上各使用一个。

  • 管道可以用于任意两个(或更多)相关进程之间的通信,只要在创建子进程的系列 fork() 调用之前通过一个共同的祖先进程创建管道即可。

  • 关闭未使用管道文件描述符对于正确使用管道非常重要的:

    • 当 read 一个写入端 (write end) 已被关闭的管道时,在所有数据都被读取后,read 会返回 0,这时读取进程就知道文件已结束了。

    • 如果读取进程没有关闭管道的写入端,那么在其他进程关闭了写入描述符之后,读取进程也不会看到文件结束,即使它读完了管道中的所有数据。

    • 当 write 一个读取端已被关闭的管道,内核会向写入进程发送一个SIGPIPE 信号。在默认情况下,这个信号会杀死进程。但进程可以捕获或忽略该信号,这时管道上的 write() 操作因 EPIPE 错误而失败。收到SIGPIPE 信号 和获得 EPIPE 错误对于可以起到标示管道状态的作用。

  • 在写管道时,常量 PIPE_BUF 规定了内核的管道缓冲区大小。

    • 如果对管道调用 write(),而且要求写的字节数小于等于 PIPE_BUF,则此操作不会与其他进程对同一管道的 write 操作交叉进行。

    • 如果有多个进程同时写一个管道,且要求写入的字节数超过 PIPE_BUF,则所写的数据可能会与其他进程所写的数据交错在一起。

    三、相关参考

    • 《UNIX 环境高级编程 - 15.2 管道》

    • 《Linux / UNIX 系统编程手册 - 44.管道和FIFO》

    • 《Linux 程序设计 - 13.进程间通信:管道》

    • 《UNIX-Linux编程实践教程 - 10.I/O 重定向和管道》

    更多值得学习的知识点:

    • 将管道作为一种进程同步的方法;

    • 使用管道连接过滤器;

    • 通过管道与 shell 命令进行通信:popen();

    • 管道和 stdio 缓冲;

    • 命名管道:FIFO; ...

    鉴于大多数人的注意力无法在一篇文章里上集中太久,更多的内容请大家自行去阅读吧,不是自己理解到的东西是消化不了的。有机会的话我会把更多的读书心得放在后面的文章。

    你和我各有一个苹果,如果我们交换苹果的话,我们还是只有一个苹果。但当你和我各有一个想法,我们交换想法的话,我们就都有两个想法了。如果你也对 嵌入式系统和开源软件 感兴趣,并且想和更多人互相交流学习的话,请关注我的公众号:嵌入式 Hacker,一起来学习吧,无论是 关注或转发 , 还是赏赐,都是对作者莫大的支持,感谢 各位的大拇指「在看」 ,,祝工作顺利,家庭和睦~

      推荐阅读:

      专辑|Linux文章汇总

      专辑|程序人生

      专辑|C语言

    嵌入式Linux

    微信扫描二维码,关注我的公众号

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

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

相关文章

JavaScript 基础,登录前端验证

1、<script></script>的三种用法&#xff1a; 1.放在<body>中 2.放在<head>中 3.放在外部JS文件中 2、三种输出数据的方式&#xff1a; 1.使用 document.write() 方法将内容写到 HTML 文档中。 2.使用 window.alert() 弹出警告框。 3.使用 innerHTML 写…

Meta的用法

----------------------------------------------- ? 这就是meta标签的典型运用。meta标签有多少参数&#xff0c;有什么作用&#xff0c;为什么我们要特别重视它呢&#xff1f;让我们一起来发掘meta标签的奥妙! ? 根据HTML语言标准注释&#xff1a;meta标签是对网站发展非常…

iOS10 打开APP设置界面和WIFI界面

在iOS10以上&#xff0c;权限这块有了一些变化 首先在info的URL Types 添加 prefs 1、打开APP设置界面 //打开设置let url:NSURL NSURL(string: UIApplicationOpenSettingsURLString)!if UIApplication.shared.canOpenURL(url as URL){ UIApplication.shared.openURL(url as…

一种简单、实用的测量程序运行时间的方法

前言 平时我们可能很少去关注程序运行的时间&#xff0c;但是在一些情况下可能需要对程序进行一个整体的复盘、优化。那么&#xff0c;程序运行的时间就是一个可以考虑的方面&#xff0c;可以测一下某些代码块、函数、算法的运行时间&#xff0c;然后整体考虑看看有没有必要进行…

可以这样给DataGrid加个序号列。

先给DataGrid加个绑定列&#xff0c;该列设置页眉文本&#xff0c;但“数据字段”留空&#xff0c;然后在ItemDataBound事件中加入下面代码。 privatevoiddgScore_ItemDataBound(objectsender, System.Web.UI.WebControls.DataGridItemEventArgs e) { …

工作几天被裁员,难受

前两天&#xff0c;一个读者朋友私聊我说&#xff0c;自己被公司裁员了&#xff0c;这是他的第一份工作&#xff0c;只工作了不到半个月就收到了裁员信息。他非常不甘心&#xff0c;也非常恐慌&#xff0c;不甘心的是&#xff0c;自己觉得工作已经非常努力&#xff0c;也有做出…

cad2017单段线_没想到啊,我平时用的CAD多段线有这么多学问

很多人都说&#xff0c;CAD用多段线来代替直线绘图会比较方便&#xff0c;因为多段线除了常规直线功能之外&#xff0c;也能画弧线&#xff0c;更重要的是&#xff0c;一次命令执行的线条为一个整体&#xff0c;操作方便。难道多段线PL仅仅只有这明面上的实力吗&#xff1f;当然…

一个超强的逆向分析软件

IDA 超强逆向分析工具先说下&#xff0c;想获取这个工具的同学&#xff0c;请在公众号后台回复 「逆向分析」获取下载链接。IDA Pro&#xff08;交互式反汇编其专业版&#xff0c;后续简称为IDA&#xff09;软件是由Hex-Rays SA公司发布&#xff0c;属于当前最炙手可热的一款世…

你还不知道怎么退出 Vim?

提起文本编辑器&#xff0c;你一定会想到编辑器之神 Vim。据 Stack Overflow 的开发者调查&#xff1a;2015 年程序员中最流行的编辑器是 Notepad&#xff0c;Vim 的使用比例占 15.2%。到了 2019 年&#xff0c;最流行的开发环境变成 VS Code&#xff0c;而 Vim 的使用比例已占…

我的大学6年

这篇文章是郭天祥前辈写的&#xff0c;想起来我上大学那时候&#xff0c;也是看他的视频入门的单片机开发&#xff0c;而且那时候&#xff0c;没有这么多渠道了解外面的东西。当时最喜欢的是一个技术论坛&#xff0c;现在还因为某种原因开始收费了&#xff0c;更甚的是如果不按…

2017.10.25水题大作战题解

rank: T1P1615 西游记公司 https://www.luogu.org/problemnew/show/P1615 scanf直接秒 1 #include<iostream>2 #include<cstdio>3 #include<cstring>4 #include<cmath>5 #define LL long long 6 using namespace std;7 inline LL read()8 {9 char …

功夫熊猫问我要不要从嵌入式转行去互联网

先看问题&#xff0c;因为我平时不怎么看微信公众号的后台&#xff0c;我比较喜欢逛知识星球和微信群&#xff0c;公众号后台的交流不是很友好&#xff0c;所以没怎么关注&#xff0c;不过也会隔三岔五的看看留言&#xff0c;比如谁给我说好听的&#xff0c;或者谁骂我了&#…

进程和线程基础知识全家桶,30 张图一套带走

前言先来看看一则小故事我们写好的一行行代码&#xff0c;为了让其工作起来&#xff0c;我们还得把它送进城&#xff08;进程&#xff09;里&#xff0c;那既然进了城里&#xff0c;那肯定不能胡作非为了。城里人有城里人的规矩&#xff0c;城中有个专门管辖你们的城管&#xf…

前端面试之前要准备的那些事

先说一下关于工作简历的一些常见的问题&#xff0c;这是最基础的一步&#xff0c;万事开头难&#xff0c;写好简历就是求职路上最简单也是最关键的一步&#xff0c;一份好的简历不但可以让你从众多简历中脱颖而出&#xff0c;还能够让公司的人事对你的印象深刻。问题一&#xf…

php ip2long bug,php ip2long函数怎么用-PHP问题

php ip2long函数用于将IPV4的字符串互联网协定转换生长整型数字&#xff0c;其应用语法是“ip2long ( string $ip_address ) : int”&#xff0c;参数“ip_address”示意一个规范格局的地点。php ip2long函数ip2long — 将 IPV4 的字符串互联网协定转换生长整型数字阐明ip2long…

C语言 | 常见数据转化函数

来源&#xff1a;嵌入式云IOT技术圈作者&#xff1a;杨源鑫整理 1、字符串转十六进制代码实现&#xff1a;void StrToHex(char *pbDest, char *pbSrc, int nLen) {char h1,h2;char s1,s2;int i;for (i0; i<nLen/2; i){h1 pbSrc[2*i];h2 pbSrc[2*i1];s1 toupper(h1) - 0x3…

java常用算法分析和实现 amp,Java常用算法实现

0.总结常见算法复杂度.jpgO(1) < O(logn) < O(n) < O(nlogn) < O(n^2) < O(n^3) < O(2^n)&#xff0c;logn的底数为21.归并排序package DailyPractice;import java.util.*;public class Test1 {/*** 归并排序的思路&#xff1a;先将数组的左边和右边分开排完…

FMStocks7 , 不错的一个.NET 示例程序

这个示例程序估计很多人都用过。没有用过的话可以从 http://www.microsoft.com/downloads/details.aspx?FamilyID966C3279-2EE9-4E14-A4F7-D4807239A396&displaylangen 下载一个简单的股票买卖程序&#xff0c;数据库访问和部分业务逻辑提供了 COM 企业服务和 DotNet Remo…

这个结构体对齐输出有意思

这个题目是我在群里看到大家讨论的&#xff0c;既然是讨论的了&#xff0c;那我就拿出来说说&#xff0c;因为笔试面试的时候&#xff0c;可能就会遇到这样的题目。实例代码#include "stdio.h" #include "stdint.h"struct Obj {char a; //1uint32_t b;//4u…

声压级 matlab,语音信号处理教程(二)声音的声压级和响度

本节内容我们来看下如何用Matlab和Python计算声音的声压级和响度。声压级1. 声压级定义首先来看声压级&#xff0c;这个就是指的我们平时所说的声音有多少分贝。声压定义为声波在某一点产生的逾量瞬时压强的均方根值。由于声压容易被人耳感知&#xff0c;也易于测量&#xff0c…