最新要闻
- 童心筑梦工匠精神
- 五一假期未到游客已至 杭州小学生要霸占北京景点了:错峰出行_观热点
- 颠覆减肥界!摄入型食欲控制胶囊问世:可治疗胃肠道疾病|今日热议
- 便宜1万块!小米电视大师86英寸Mini LED对比索尼旗舰 画质无限接近
- 天天滚动:阔别20年终于回家了!旅美大熊猫“丫丫”专机已降落上海
- 圆形模组设计瞩目!真我11系列上架预约:超越影像旗舰
- 年报看复苏| 2022年上市房企减员超10万人,仍有房企薪资上涨 专家:今年情况会有所改善 世界速讯
- 存款利率下调,提前还贷和投资黄金是好的选择吗?
- 2023KPL春季赛总决赛将于5月13日在杭州电竞中心举办 通讯
- 即时:男子考科目一作弊 竟在假发内藏“黑科技”设备
- 世界消息!3天内3死2伤!印度一矿工下班路上遭雷击身亡
- 手游也有FSR、DLSS了 高通推出骁龙GSR:游戏秒变4K、性能翻倍 世界速读
- 突发爆炸一死一伤!空调竟成“定时炸弹”:还能放心用吗?
- 世界通讯!五一假期高速公路流量将破历史峰值:预计日均超5000万辆
- 进击科技美次元,欧莱雅2023 BRANDSTORM中国大陆总决赛完美收官|每日播报
- 艾迪药业艾邦德 复邦德 上市发布会盛大召开 快播报
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
进程
进程、轻量级进程和线程
进程在教科书中通常定义:进程是程序执行时的一个实例,可以把它看作充分描述程序已经执行到何种程度的数据结构的汇集。
从内核的观点,进程的目的就是担当分配系统资源(CPU时间、内存等)的实体。
当一个进程被创建时,他几乎于父进程相同。它接受父进程地址空间的一个(逻辑)拷贝,并从进程创建系统调用的下一条指令开始执行于父进程相同的代码。尽管父子进程可以共享含有程序代码(正文)的页,但是他们各自有独立的数据拷贝(栈和堆),因此子进程对一个内存单元的修改对父进程是不可见的。
【资料图】
Unix中一个进程由几个线程组成,每个线程都代表进程的一个执行流。从内核观点来看,多线程应用程序仅仅是一个普通进程。多线程应用程序多个执行流的创建、处理、调度整个都是在用户态进行的。
Linux使用轻量级进程对多线程应用程序提供更好的支持。两个轻量级进程基本上可以共享一些资源,诸如地址空间、打开的文件等。只要其中一修改共享资源,另一个就立即查看这种修改。
实现多线程应用程序的一个简单方式就是轻量级进程与每个线程关联起来,保证共享资源的同时,每个线程都可以由内核独立调度。
进程描述符
进程描述符都是task_struct类型结构,它的字段包含了与一个进程相关的所有信息。
进程状态
进程描述符中的state字段描述了进程当前所处的状态。
可运行状态(TASK_RUNNING):进程要么在CPU执行,要么准备执行。
可中断的等待状态(TASK_INTERRUPTIBLE):进程被挂起(睡眠),直到某个条件为真。产生一个硬件中断,释放当前的进程资源,或传递一个唤醒的信号。
不可中断的等待状态(TASK_UNINTERRUPTIBLE):与可中断的等待状态类似,有个例外信号传递不能改变状态。用的很少,某些情况下(进程必须等待,直到一个不能被中断的事件发生)。例如,当进程打开一个设备文件,其相应的驱动程序开始探测相应的硬件设备时会用到,在探测完成前,设备驱动程序不能被中断,否则,硬件设备会处于不可预知的状态。
暂停状态(TASK_STOPPED):进程执行被暂停,当进程收到SIGTOP、SIGTSTP、SIGTTIN或SIGTTOU信号后,进入暂停状态。
跟踪状态(TASK_TRACED):进程的执行已由debugger程序暂停。当进程被另一个进程监控时,任何信号都可以把这个进程置于该状态。
还有两个状态既可以放在进程描述符的state字段,又可以放在exit_state字段中。当进程被终止时,进程的状态才会变成两种状态的一种:
僵死状态(EXIT_ZOMBIE):进程的执行被终止,但是父进程还没有发布wait4()或waitpid()系统调用来返回有关死亡进程的信息。发布wait()类系统调用前,内核不能丢弃包含在死进程描述符中的数据,因为父进程可能还需要它。
僵死撤销状态(EXIT_DEAD):最终状态,由于父进程刚发出wait4()或waitpid()系统调用,因而进程由系统删除。为了防止其他执行线程在同一个进程上也执行wait()类系统调用(这是一种竞争条件),而把进程的状态由僵死改为僵死撤销状态。
进程链表
采用双向链表把所有进程的描述符链接起来。
图
每个task_struct结构都包含一个list_head类型的tasks字段,这个类型的prev和next字段分别指向前面和后面的task_struct元素。
进程链表的头是init_task描述符,它是所谓的0进程(process0)或swapper进程的进程描述符。init_task的task.prev字段指向链表中最后插入的进程描述符的tasks字段。
TASK_RUNNING状态的进程链表
当内核寻找一个新进程在CPU上运行时,必须考虑可运行进程。
提高调度程序运行速度的诀窍时建立多个可运行的程序链表,每种进程优先权对应一个不同的链表。每个task_struct描述符包含一个list_head类型的字段run_list,用于保存可运行程序的优先级。在多处理器系统中,每个CPU都有自己的运行队列,即他自己的进程链表集。
运行队列的主要数据结构是组成运行队列的进程描述符链表,由一个单独的priio_array_t数据结构来实现。
p95图
进程间的关系
程序创建具有父子关系。如果一个进程创建多个子进程时,则子进程之间具有兄弟关系。
进程0和进程1是由内核创建的,进程1(init)是所有进程的祖先。
为了加速查找。引入了4个散列表,没中过类型的PID需要他自己的散列表。
p97图
Linux利用双向链表来处理冲突的PID,每一个表项都是由冲突的进程描述符组成的双向链表。
等待队列
等待队列由双向链表实现,其元素包括指向进程描述符的指针,等待队列头是一个类型为wait_queue_head_t的数据结构。
struct __wait_queue_head{ spinlock_t lock; struct list_head task_list;};typedef struct __wait_queue_head wait_queue_head_t;
因为等待队列是由中断处理函数和主要内核函数修改的,因此必须对其双向链表进行保护以免对其进行访问。同步是通过等待队列头中的lock自旋锁达到。
等待队列链表中的元素类型为wait_queue_t:
struct __wait_queue{ unsigned int flags; struct task_struct * task; wait_queue_func_t func; struct list_head task_list;};typedef struct __wait_queue wait_queue_t;
描述符地址存放在task字段中,task_list字段包含的是指针,由这个指针把一个元素连接到等待相同事件的进程链表中。
有两种睡眠进程:互斥进程(flags=1)由内核有选择的唤醒,而非互斥进程(flags=0)总是由内核在事件发生时唤醒。等待访问临界资源的进程就是互斥的,等待相关事件的进程时非互斥的,func字段表示唤醒的方式。
一旦定义了一个元素,必须把它插入等待队列。add_wait_queue()函数把一个非互斥进程插入等待队列链表的第一个位置,add_wait_queue_exclusive()函数把一个互斥进程插入等待队列链表的最后一个位置。remove_wait_queue()函数从等待队列链表中删除一个进程。waitqueue_active()函数检查一个给定的等待队列是否为空。
wake_up_locked宏和wake_up宏相类似,仅有的不同是当wait_queue_head_t中的自旋锁已经被持有时要调用wake_up_locked;
例如,wake_up宏等价于下列代码:
void wake_up(wait_queue_head_t *q){ struct list_head *tmp; wait_queue_t *curr; list_for_each(tmp,wait_queue_t,task_list){ curr = list_entry(tmp,wait_queue_t,task_list); if(curr->func(curr, TASK_INTERRUPTIBLE|TASK_UNINTERRUPTBLE,0,NULL) && curr->flags) break; }}
list_for_each宏扫描双向链表中的所有项,即等待队列的所有进程。对每一项,list_entry宏都计算wait_queue_t变量对应的地址。这个变量的func字段存放唤醒函数的地址,它试图唤醒由等待队列元素的task字段标识的进程。如果一个进程已经被有效地唤醒并且进程是互斥的,循环结束。
因为所有的非互斥进程总是在双向链表的开始位置,而所有的互斥进程在双向链表的尾部,所以函数总是先唤醒非互斥进程然后再唤醒互斥进程,如果有进程存在的话。
进程切换
为了控制进程的执行,内核必须有能力挂起正在CPU上运行的进程,并恢复以前挂起的某个进程的执行。这种行为被称为进程切换、任务切换或上下文切换。
硬件上下文
进程恢复执行前必须装入寄存器的一组数据称为硬件上下文。硬件上下文是进程可执行上下文的一个子集,因为可执行上下文包含进程执行所需要的所有信息。在Linux中,进程硬件上下文的一部分存放在TSS段,而剩余部分存放在内核态堆栈中。
prev--切换出的进程的描述符 next--切换进的进程的描述符
我们把进程切换定义为这样的行为:保存prev硬件上上下文,用next硬件上下文代替prev。
执行进程切换
从本质上说,每个进程切换由两部组成:
1、切换页全局目录以安装一个新的地址空间;
2、切换内核态堆栈和硬件上下文,因为硬件上下文提供了内核执行新进程所需要的所有信息,包含CPU寄存器。
switch_to宏
进程切换的第二步由switch_to宏执行,它是内核中与硬件关系最密切的历程之一。
他有三个参数,prev、next 和 last。
在任何进程切换中涉及到三个进程而不是两个进程,假设内核决定暂停进程A而激活进程B。在shedule()函数中,prev指向A的描述符而next指向B的描述符。switch_to宏一旦使A暂停,A的执行流就冻结。随后,当内核想再次激活进程A,就必须暂停另一个进程C,于是就要用prev指向C而next指向A来执行另一个switch_to宏。
switch_to宏的最后一个参数是输出参数,它表示宏把进程C的描述符地址写在内存的什么位置了。
p110图
创建进程
clone()、fork()及 vfork()系统调用
在Linux中,轻量级进程是由名为clone()的函数创建的。
传统的fork()系统调用在Linux中是用clone()实现的,其中clone()的flags参数指定为SIGCHLD信号及所有清0的clone标志,而它的child_stack参数是父进程当前的堆栈指针。因此,父进程和子进程暂时共享一个用户态堆栈。
要感谢写时复制机制,通常只要父子进程中有一个试图去改变,则立即各自的到用户态堆栈的一份拷贝。
do_fork()函数负责处理clone()、fork()和vfork()系统调用,利用辅助函数 copy_process()来创建进程描述符以及子进程所需要的内核数据结构。
do_fork()之后有了处于可运行状态的完整子进程,但他还没有实际运行,调度程序决定何时把CPU交给这个子进程。在以后的进程切换中,调度程序将继续完善子进程。然后,在fork()、vfork()、clone()系统调用结束后,新进程将开始执行。系统调用的返回值放在eax寄存器中,返回给子进程的值是0,返回给父进程的是子进程的PID。
内核线程
现代操作系统将一些重要的任务交给内核线程,内核线程不受不必要的用户态上下文的拖累,这些任务包括刷新磁盘高速缓存,交换出不用的页框,维护网络连接等等。在Linux中,内核线程在以下几个方面不用于普通进程:
内核线程之运行在内核态,而普通进程既可以运行在内核态,也可以运行在用户态。
内核线程只使用大于PAGE_OFFSET的线性地址空间,普通进程可以用4GB的线性地址空间。
创建一个内核线程
kernel_thread()函数创建一个新的内核线程,它接受的参数由:所要指向的内核函数的地址(fn)、要传递给函数的参数(arg)、一组clone标志(flags)。该函数本质以下面方式调用do_fork():
do_fork(flags|CLONE_UNTRACED, 0, pregs, 0, NULL, NULL);
CLONE_VM标志避免复制调用进程的页表,CLONE_UNTRACED标志保证不会有任何进程跟踪。
传递给do_fork()的参数pregs表示内核栈的地址,copy_thread()函数将从这里找到新线程初始化CPU寄存器的值。
进程0
所有进程的祖先叫做进程0,idel进程或因为历史的渊源叫做swapper进程,它是在Linux的初始化阶段从无到有创建的一个内核线程,这个祖先进程使用下列静态分配的数据结构:
存放在 init_task 变量中的进程描述符,由 INIT_TASK 宏完成对它的初始化
存放在 init_thread_union 变量中的 thread_info 描述符和内核堆栈,由 INIT_THREAD_INFO 宏完成对它们的初始化
start_kernel()函数初始化内核需要的所有数据结构,激活中断,创建另一个叫进程1 的内核线程(一般叫做init进程):
kernel_thread(init, NULL, CLONE_FS|CLONE_SIGHAND);
新创建的内核线程的PID为1,并于进程0共享每进程所有的内核数据结构。此外,当调度程序选择到它时,init 进程开始执行init()函数。
在多处理器系统中,每个CPU都有一个进程0。打开电源,计算机的BIOS就启动某一个CPU,同时禁用其他CPU。运行在CPU 0上的swapper进程初始化内核数据结构,然后激活其他的CPU,并通过copy_process()函数创建另外的swapper进程,把0传递给新创建的swapper进程作为它们的新PID。
进程1(init进程)
由进程0创建的内核线程执行init()函数,init()依此完成内核初始化。init()调用execve()系统调用装入可执行程序init。结果,init内核线程变成一个普通进程,且拥有自己的每进程内核数据结构。在系统关闭之前,init进程一直存活,因为它创建和监控在操作系统外层执行的所有进程的活动。
其他内核线程
Linux使用很多其他内核线程,其中一些在初始化阶段创建,一直运行到系统关闭,而其他一些在内核必须执行一个任务时“按需”创建,这种任务在内核的执行上下文中得到很好的执行。
进程撤销
进程终止
在Linux2.6中有两个终止用户态应用的系统调用:
exit_group()系统调用,它终止整个线程组,即整个基于多线程的应用。do_group_exit()是实现这个系统调用的主要内核函数。这是C库函数应该调用的系统调用。
exit()系统调用,它终止某一个线程,而不管该线程所属线程组中的所有其他线程。do_exit()是实现这个系统调用的主要内核函数,这是被诸如 pthread_exit()的Linux线程库的函数所调用的系统调用。
关键词:
进程
Python数据类型|全球报资讯
环球热点!记一次峰回路转的注入
linux基本命令
这8个摸鱼神器,千万别让你老板知道!
童心筑梦工匠精神
五一假期未到游客已至 杭州小学生要霸占北京景点了:错峰出行_观热点
颠覆减肥界!摄入型食欲控制胶囊问世:可治疗胃肠道疾病|今日热议
便宜1万块!小米电视大师86英寸Mini LED对比索尼旗舰 画质无限接近
天天滚动:阔别20年终于回家了!旅美大熊猫“丫丫”专机已降落上海
圆形模组设计瞩目!真我11系列上架预约:超越影像旗舰
年报看复苏| 2022年上市房企减员超10万人,仍有房企薪资上涨 专家:今年情况会有所改善 世界速讯
火山引擎 DataLeap 下 Notebook 系列文章三:架构升级详解 世界热文
RPM常用命令以及组合使用场景 全球热闻
存款利率下调,提前还贷和投资黄金是好的选择吗?
【新华500】新华500指数(989001)27日收涨0.68%-通讯
2023KPL春季赛总决赛将于5月13日在杭州电竞中心举办 通讯
即时:男子考科目一作弊 竟在假发内藏“黑科技”设备
世界消息!3天内3死2伤!印度一矿工下班路上遭雷击身亡
手游也有FSR、DLSS了 高通推出骁龙GSR:游戏秒变4K、性能翻倍 世界速读
突发爆炸一死一伤!空调竟成“定时炸弹”:还能放心用吗?
世界通讯!五一假期高速公路流量将破历史峰值:预计日均超5000万辆
进击科技美次元,欧莱雅2023 BRANDSTORM中国大陆总决赛完美收官|每日播报
信息:开心档之C++ STL 教程
CutMix&Mixup详解与代码实战
ASP.NET Core MVC 从入门到精通之数据库|热点聚焦
焦点日报:web: pdf_converter | DASCTF Apr.2023 X SU战队2023开局之战
只需六步!快速开启专属的风控系统
艾迪药业艾邦德 复邦德 上市发布会盛大召开 快播报
仅重998g!LG推出Gram SuperSlim笔电:10.9mm纤薄机身
锐龙R9-7945HX游戏本实测:性能恐怖 渲染能力媲美桌面版-环球快看
国产芯片新突破!龙芯3A5000成功应用于3D打印|焦点热门
最资讯丨画二次元画首先学什么,南京二次元画哪里可以学
全球速讯:饼状图的优缺点,你真的了解吗?
高保真智能录音机解决方案技术特色解析 当前要闻
使用ethtool排查网卡速率问题 世界动态
海大集团接待AllianzGlobal等多家机构调研|全球时快讯
谷歌创始人大量抛售特斯拉股票:曾被曝马斯克绿了他 今日讯
光刻机订单占了30% ASML喊话:绝对不能失去中国市场_天天头条
.NET使用一行命令轻松生成EF Core项目框架
环球精选!【解决方法】正常游览Flash页面,解决主流游览器的不支持问题(如Edge,Firefox)
今日快讯:小米盒子怎么看电视直播_小米盒子看电视直播的方法
男子聊天界面投屏广场成大型社死现场:全网都知道他不回老婆微信了 重点聚焦
每日精选:首例涉“虚拟数字人”侵权案宣判:被告判消除影响并赔12万
每日动态!89英寸三星MICRO LED电视全球首秀:RGB无机自发光、支持音画追踪
研究所预测:2070年日本总人口将降至8700万-每日时讯
华为88W充电器A/C口二选一引争议 华为李小龙:对用户最友好的设计_快资讯
世界快报:小小善举 温暖一座城!搀扶残障人士过马路的暖心司机找到了
每日快播:CloudCanal x OceanBase 数据迁移同步优化
JS中的promise返回的resolve()和reject()的理解附代码展示
韩媒:拜登向尹锡悦推荐“零度可乐”,韩网友嘲讽“给你的也只有零”_全球热闻
苹果手机黑屏但是有声音是怎么回事?苹果手机黑屏但是有声音怎么解决?
联想k860什么时候上市的?联想k860手机参数
焦点日报:马斯克疯狂降价!特斯拉Model Y已比美国新车平均价还便宜
环球看热讯:人工智能“走出”电脑!Spot机械狗成功集成ChatGPT
国产最强骁龙8 Gen2折叠屏!vivo X Fold2明天首销:8999元起
友商被苹果干趴 华为撑起国货尊严:一季度销量暴涨41%!没5G依然强-新资讯
求职者嫌8000工资高要求降到2000:HR信以为真改标准 世界今热点
电脑k歌需要什么设备?电脑k歌软件哪个好用?
2022中国男排大名单是什么?中国男排联赛2022年赛程
麦当劳被中国买下了吗?金拱门为什么还叫麦当劳?
三星堆是哪个朝代的?三星堆文明是什么民族?
佳禾智能:2022年净利润续创新高,一季度业绩强势增长|视点
为什么很多人喜欢罗永浩?罗永浩创立的手机品牌是什么?
明日方舟六星强度榜是什么?明日方舟真正的三幻神
街头霸王哪个人物最厉害?12人街霸人物原型
中国十大导演有哪些?中国内地四大导演排名
数栈V6.0全新产品矩阵发布,数据底座 EasyMR 焕新升级|世界快消息
天天热门:高清录音机市场需求调研分析
python-docx对替换后的文字设置英文字体、中文字体、字号大小、对齐方式-焦点短讯
天天短讯!东西问丨马特博博耶夫:明铁佩古城遗址为何被称为“丝绸之路活化石”?
每日热议!爱美客(300896):1Q净利润高增 厚积薄发增长势头足
上海大力建设“墨水屏”公交站牌 今年五个新城覆盖率超50%
真能横着开!现代摩比斯“e-Corner”实车演示:再不怕侧方停车了_环球即时看
王健林抛弃万达汽车
天天亮点!首发9999元 惠普暗影精灵9 SLIM上架:i9+ RTX 4060
脚感软弹 静音防滑:三福EVA洞洞拖鞋14.1元大促(原价29元) 天天速读
央行今日实现净投放590亿元
VueRouter 天天微头条
全球新消息丨WPF教程_编程入门自学教程_菜鸟教程-免费教程分享
基于Java开发支持全文检索、工作流审批、知识图谱的应用系统
前端跨域解决方案——CORS
【环球播资讯】湖北宜昌三年改造367座危桥
天天即时看!丰田:智能不是堆砌功能 制造让中国人感到喜悦的汽车
今亮点!真我11系列外观首秀:荔枝纹素皮、金色圆环抢眼
强过骁龙8 Gen3!iQOO Neo8 Pro首发天玑9200+稳了_全球热点评
全球百事通!工信部:尽快明确2023年后车购税减免政策
曾红极一时的天涯社区已无法打开 消息称欠了千万元服务器费_全球今日讯
【单例设计模式原理详解】Java/JS/Go/Python/TS不同语言实现
【世界新要闻】国防部新闻发言人谭克非就中国军队派军舰紧急撤离我在苏丹人员发表谈话
今日快看!【财经分析】深圳市4月地方债定价连续“换锚” 市场化发行水平不断提升
大熊猫丫丫启程画面曝光 网友哽咽:一路平安
5999元起!小米13 Ultra改变了米粉不爱拍照的习惯 全球速讯
全球播报:暗黑预售推动暴雪营收大幅增长
世界速递!超讯通信:2022年度净利润约1519万元
学习Linux,你提上日程了吗?
“五一”出游高峰将至 各地文旅部门多举措“迎考”
【国际大宗商品早报】国际油价显著下跌 基本金属多数上涨
郑和下西洋最远到达了哪里_郑和下西洋最远的地方|每日精选
环球短讯!小米14曝光:采用华星屏幕 边框比iPhone 14 Pro更窄