转 shell中的多进程【并发】
原文地址https://bbs.51cto.com/thread-1104907-1-1.html
根据我个人的理解, 所谓的多进程 只不过是将多个任务放到后台执行而已,很多人都用到过,所以现在讲的主要是控制,而不是实现。
先看一个小shell:

看执行结果:

很明显是8s
=============================
这种不占处理器却有很耗时的进程,我们可以通过一种后台运行的方式
来达到节约时间的目的。看如下改进:

用“{}”将主执行程序变为一个块,用&放入后台,四次执行全部放入后台后,我们
需要用一个wait指令,等待所有后台进程执行结束,
不然 系统是不会等待的,直接继续执行后续指令,知道整个程序结束。
看结果:

可以看到,时间已经大大缩短了!
============================
以上实验虽然达到了多线程并发的目的,但有一个缺陷,不能控制
运行在后台的进程数。
为了控制进程,我们引入了管道 和文件操作符。
无名管道: 就是我们经常使用的 例如: cat text | grep "abc"
那个“|”就是管道,只不过是无名的,可以直接作为两个进程的数据通道
有名管道: mkfilo 可以创建一个管道文件 ,例如: mkfifo fifo_file
管道有一个特点,如果管道中没有数据,那么取管道数据的操作就会停滞,直到
管道内进入数据,然后读出后才会终止这一操作,同理,写入管道的操作
如果没有读取操作,这一个动作也会停滞。

当我们试图用echo想管道文件中写入数据时,由于没有任何进程在对它做读取操作,所以
它会一直停留在那里等待读取操作,此时我们在另一终端上用cat指令做读取操作

你会发现读取操作一旦执行,写入操作就可以顺利完成了,同理,先做读取操作也是一样的:
由于没有管道内没有数据,所以读取操作一直滞留在那里等待写入的数据

一旦有了写入的数据,读取操作立刻顺利完成
以上实验,看以看到,仅仅一个管道文件似乎很难实现 我们的目的(控制后台线程数),
所以 接下来介绍 文件操作符,这里只做简单的介绍,如果不熟悉的可以自行查阅资料。
系统运行起始,就相应设备自动绑定到了 三个文件操作符 分别为 0 1 2 对应 stdin ,stdout, stderr 。
在 /proc/self/fd 中 可以看到 这三个三个对应文件


输出到这三个文件的内容都会显示出来。只是因为显示器作为最常用的输出设备而被绑定。
我们可以exec 指令自行定义、绑定文件操作符
文件操作符一般从3-(n-1)都可以随便使用
此处的n 为 ulimit -n 的定义值得
可以看到 我的 n值为1024 ,所以文件操作符只能使用 0-1023,可自行定义的 就只能是 3-1023 了。
直接上代码,然后根据代码分析每行代码的含义:

第3行: 接受信号 2 (ctrl +C)做的操作
exec 1000>&-和exec 1000<&- 是关闭fd1000的意思
我们生成做绑定时 可以用 exec 1000<>testfifo 来实现,但关闭时必须分开来写
> 读的绑定,< 标识写的绑定 <> 则标识 对文件描述符 1000的所有操作等同于对管道文件
testfifo的操作。
第5-7行: 分别为 创建管道文件,文件操作符绑定,删除管道文件
可能会有疑问,为什么不能直接使用管道文件呢?
事实上,这并非多此一举,刚才已经说明了管道文件的一个重要特性了,那就是读写必须同时存在
缺少某一种操作,另一种操作就是滞留,而绑定文件操作符 正好解决了这个问题。
(至于为什么,我还没研究明白,有知道的 还请告知,谢谢)
第9-12 行: 对文件操作符进行写入操作。 通过一个for循环写入10个空行,这个10就是我们要定义的后台线程数量。
为什么写入空行而不是10个字符呢 ?
这是因为,管道文件的读取 是以行为单位的。

当我们试图用 read 读取管道中的一个字符时,结果是不成功的,而刚才我们已经证实使用cat是可以读取的。
第17-24行: 这里假定我们有100个任务,我们要实现的时 ,保证后台只有10个进程在同步运行 。
read -u1000 的作用是:读取一次管道中的一行,在这儿就是读取一个空行。
减少操作附中的一个空行之后,执行一次任务(当然是放到后台执行),需要注意的是,这个任务在后台执行结束以后
会向文件操作符中写入一个空行,这就是重点所在,如果我们不在某种情况某种时刻向操作符中写入空行,那么结果就是:
在后台放入10个任务之后,由于操作符中没有可读取的空行,导致 read -u1000 这儿 始终停顿。
后边的 就不用解释了,贴下执行结果:


每次的停顿中都能看到 只有10个进程在运行
一共耗时50s
一共100个任务,每次10个 ,每个5s 正好50s
上边的结果图之所以这么有规律,这是因为我们所执行的100个任务耗时都是相同的,
比如,系统将第一批10个任务放入后台的过程所消耗的时间 几乎可以忽略不计,也就是说
这10个任务几乎可以任务是同时运行,当然也就可以认为是同时结束了,而按照刚才的分析,
一个任务结束时就会向文件描述符写入空行,既然是同时结束的,那么肯定是同时写入的空行,
所以下一批任务又几乎同时运行,如此循环下去的。
实际应用时,肯定不是这个样子的,比如,第一个放到后台执行的任务,是最耗时间的,
那他肯定就会是最后一个执行完毕。
所以,实际上来说,只要有一个任务完成,那么下一个任务就可以被放到后台并发执行了。
转 shell中的多进程【并发】的更多相关文章
- shell中的多进程【并发】(转)
http://bbs.51cto.com/thread-1104907-1-1.html
- shell——wait与多进程并发
在脚本里用&后台打开多个子进程,用wait命令可以使这些子进程并行执行. 例1: fun1(){ while true do echo 1 sleep 1 done } fun2(){ whi ...
- python 多进程并发与多线程并发
本文对python支持的几种并发方式进行简单的总结. Python支持的并发分为多线程并发与多进程并发(异步IO本文不涉及).概念上来说,多进程并发即运行多个独立的程序,优势在于并发处理的任务都由操作 ...
- Linux Shell多进程并发以及并发数控制
1. 基础知识准备 1.1. linux后台进程 Unix是一个多任务系统,允许多用户同时运行多个程序.shell的元字符&提供了在后台运行不需要键盘输入的程序的方法.输入命令后,其后紧跟&a ...
- python多进程并发和多线程并发和协程
为什么需要并发编程? 如果程序中包含I/O操作,程序会有很高的延迟,CPU会处于等待状态,这样会浪费系统资源,浪费时间 1.Python的并发编程分为多进程并发和多线程并发 多进程并发:运行多个独立的 ...
- Python中使用多进程来实现并行处理的方法小结
进程和线程是计算机软件领域里很重要的概念,进程和线程有区别,也有着密切的联系,先来辨析一下这两个概念: 1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和 ...
- shell中wait命令详解
wait命令介绍 wait [作业指示或进程号] 1.等待作业号或者进程号制定的进程退出,返回最后一个作业或进程的退出状态状态.如果没有制定参数,则等待所有子进程的退出,其退出状态为0. 2.如果是s ...
- 聊聊Python中的多进程和多线程
今天,想谈一下Python中的进程和线程. 最近在学习Django的时候,涉及到了多进程和多线程的知识点,所以想着一下把Python中的这块知识进行总结,所以系统地学习了一遍,将知识梳理如下. 1. ...
- Appium+python自动化(三十六)- 士兵突击许三多 - 多个appium服务启动,多个设备启动,多进程并发启动设备-并发测试 - 上(超详解)
简介 前面课程只是启动了单个appium服务,只能控制单台设备.如果需要针对多台设备测试那么该如何处理?而且发现群里的小伙伴们也在时不时地在讨论这个问题,想知道怎么实现的,于是宏哥就决定写一片这样的文 ...
随机推荐
- SpringCloud简历模板
项目三:智慧生鲜(SpringCloud) 开发周期:5个月项目介绍:该项目是一个基于微服分布式的生鲜电商网站,主要模块有前台:用户模块.商品模块.购物车模块.订单模块.支付模块.抢购模块.后台:权限 ...
- linux下安装mysql5.7方法与常见问题
linux上安装mysql5.7 1.下载tar包,这里使用wget从官网下载 wget https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7 ...
- 基于模板匹配的目标跟踪(OpenCV)
基于VS2010+ OpenCV2.代码可以读入视频,也可以读摄像头,两者的选择只需要在代码中稍微修改即可.对于视频来说,运行会先显示第一帧,然后我们用鼠标框选要跟踪的目标,然后跟踪器开始跟踪每一帧. ...
- odoo10实现单点登陆绕过登陆集成页面
背景:由于需要集成odoo平台在其他页面,需要绕开登陆. 解决办法:开辟一个自动登陆的路由用与集成页面. 1.修改web模块中controller/main.py文件,在class名字为Home中添加 ...
- centos7安装oracle1201c
root身份安装依赖包: yum -y install binutils compat-libcap1 compat-libstdc++-33 compat-libstdc++-33*.i686 el ...
- Springmvc使用注解实现执行定时任务(定时器)
1.在Spring配置文件中添加 <task:annotation-driven/> 2.在需要调用执行定时任务的类中使用注解 @Service @Lazy(false) //避免spri ...
- python---博客分类目录
python基础 python函数 python模块 python面向对象 网络编程 并发编程 数据库 前端学习 HTML基础 CSS基础 JavaScript基础 js操作BOM和DOM jQuer ...
- C# 不用添加WebService引用,调用WebService方法
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行. [System.Web.Script.Services.ScriptService] 使用HttpWeb ...
- 进阶Java编程(10)反射与简单Java类
1,传统属性自动赋值弊端 简单Java类主要由属性构成,并且提供有setter与getter类,同时简单Java类最大的特征就是通过对象保存相应的类属性的内容.但是如果使用传统的简单Java类开发,那 ...
- 题解 P2661 【信息传递】
首先介绍个概念:基环外向树,也叫环加外向树,环基树,章鱼图. 这就是一颗基环外向树. 不难发现,若基环外向树有n个结点就有n条边,这也意味 着它不是颗普通的树,而是必定有一个自环. 再看看题目中的介绍 ...