一条 shell 命令的阻塞与唤醒

f1992fcb3fe97302047e3f7ef22b2a9c.gif

作者 | 闪客

来源 | CSDN博客

新建一个非常简单的 info.txt 文件。

name:flash
age:28
language:java

在命令行输入一条十分简单的命令。

[root@linux0.11] cat info.txt | wc -l
3

这条命令的意思是读取刚刚的 info.txt 文件,输出它的行数。

我们之前分析了一下 shell 进程是如何读取你的命令的,流程如下图。

ee3a7fda6369945325426f42f84d53a8.png

当然,这里的 sleep_onwake_up 是进程的阻塞与唤醒机制的实现,我们没有展开讲解。

那我们今天,就详细看看这块的逻辑。

首先,表示进程的数据结构是 task_struct,其中有一个 state 字段表示进程的状态,它在 Linux 0.11 里有五种枚举值。

// shed.h
#define TASK_RUNNING 0      // 运行态
#define TASK_INTERRUPTIBLE 1    // 可中断等待状态。
#define TASK_UNINTERRUPTIBLE 2  // 不可中断等待状态
#define TASK_ZOMBIE 3       // 僵死状态
#define TASK_STOPPED 4      // 停止

当进程首次被创建时,也就是 fork 函数执行后,它的初始状态是 0,也就是运行态。

// system_call.s
_sys_fork:...call _copy_process...// fork.c
int copy_process(...) {...p->state = TASK_RUNNING;...
}

只有当处于运行态的进程,才会被调度机制选中,送入 CPU 开始执行。

// sched.c
void schedule (void) {...if ((*p)->state == TASK_RUNNING && (*p)->counter > c) {...next = i;}...switch_to (next);
}

以上我简单列出了关键代码,基本可以描绘进程调度的大体框架。 

所以,使得一个进程阻塞的方法非常简单,并不需要什么魔法,只需要将其 state 字段,变成非 TASK_RUNNING 也就是非运行态,即可让它暂时不被 CPU 调度,也就达到了阻塞的效果。

同样,唤醒也非常简单,就是再将对应进程的 state 字段变成 TASK_RUNNING 即可。

Linux 0.11 中的阻塞与唤醒,就是 sleep_on 和 wake_up 函数。

其中 sleep_on 函数将 state 变为 TASK_UNINTERRUPTIBLE。

// sched.c
void sleep_on (struct task_struct **p) {struct task_struct *tmp;...tmp = *p;*p = current;current->state = TASK_UNINTERRUPTIBLE;schedule();if (tmp)tmp->state = 0;
}

而 wake_up 函数将 state 变回为 TASK_RUNNING,也就是 0。

// sched.c
void wake_up (struct task_struct **p) {(**p).state = 0;
}

是不是非常简单?

当然 sleep_on 函数除了改变 state 状态之外,还有些难理解的操作,我们先试着来分析一下。

当首次调用 sleep_on 函数时,比如 tty_read 在 secondary 队列为空时调用 sleep_on,传入的 *p 为 NULL,因为此时还没有等待 secondary 这个队列的任务。

struct tty_queue {... struct task_struct * proc_list;
};struct tty_struct {...struct tty_queue secondary;
};int tty_read(unsigned channel, char * buf, int nr) {...sleep_if_empty(&tty->secondary);...
}static void sleep_if_empty(struct tty_queue * queue) {...interruptible_sleep_on(&queue->proc_list);...   
}

通过 tmp = *p*p = current 两个赋值操作,此时:

tmp = NULL

*p = 当前任务

同时也使得 proc_list 指向了当前任务的 task_struct。

9c008b5a14fea4dda75822f6c74a0d42.png

当有另一个进程调用了 tty_read 读取了同一个 tty 的数据时,就需要再次 sleep_on,此时携带的 *p 就是一个指向了之前的"当前任务"的结构体。

那么经过 tmp = *p 和 *p = current 两个赋值操作后,会变成这个样子。

3a271363f1fdbb67b4e844e0b3b8ed89.png

也就是说,通过每一个当前任务所在的代码块中的 tmp 变量,总能找到上一个正在同样等待一个资源的进程,因此也就形成了一个链表。

那么,当某进程调用了 wake_up 函数唤醒 proc_list 上指向的第一个任务时,改任务变会在 sleep_on 函数执行完 schedule() 后被唤醒并执行下面的代码,把 tmp 指针指向的上一个任务也同样唤醒。

// sched.c
void sleep_on (struct task_struct **p) {struct task_struct *tmp;...tmp = *p;*p = current;current->state = TASK_UNINTERRUPTIBLE;schedule();if (tmp)tmp->state = 0;
}

永远记住,唤醒其实就是把 state 变成 0 而已。

而上一个进程唤醒后,和这个被唤醒的进程一样,也会走过它自己的 sleep_on 函数的后半段,把它的上一个进程,也就是上上一个进程唤醒。 

那么上上一个进程,又会唤醒上上上一个进程,上上上一个进程,又会...

看懂了没,通过一个 wake_up 函数,以及上述这种 tmp 变量的巧妙设计,我们就能制造出唤醒的一连串连锁反应。

当然,唤醒后谁能优先抢到资源,那就得看调度的时机以及调度的机制了,对我们来说相当于听天由命了。

OK,现在我们的 shell 进程,通过 read 函数,中间经过了层层封装,以及后面经过了阻塞与唤醒这一番折腾后,终于把键盘输入的字符们,成功由 tty 中的 secondary 队列,读取并存放与 buf 指向的内存地址处。

[root@linux0.11] cat info.txt | wc -l

接下来,就该解析并执行这条命令了。

// xv6-public sh.c
int main(void) {static char buf[100];// 读取命令while(getcmd(buf, sizeof(buf)) >= 0){// 创建新进程if(fork() == 0)// 执行命令runcmd(parsecmd(buf));// 等待进程退出wait();}
}

也就是上述函数中的 runcmd 命令。

0279b27770542b3bd4bd7f9346fdf311.gif

往期推荐

Docker 那些事儿:如何安全地停止、删除容器?

使用 nginx 轻松管理 kubernetes 资源文件

Redis 内存满了怎么办?这样置才正确!

实战 Kubectl 创建 Deployment 部署应用

106a3c5829f3943b885281b203acc565.gif

点分享

804e624386d23e6247d6c25abe57176f.gif

点收藏

d4c566983bf674a642a52c1933160d79.gif

点点赞

fa1f925401c3c5015da0d533baf51a40.gif

点在看

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

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

相关文章

21克:仅需3天,我们就用Quick BI搭建起数据驾驶舱

简介:数智化并不仅仅是大型企业才需要去思考的课题,而是摆在所有企业面前的一个可选项。借助Quick BI搭建的数据分析体系,21克实现了销售、财务、供应链等多部门业务的数据化支撑,从一份份本地化的Excel文件,到清晰美观…

新监管形势下的数据流通合规技术解最新探究 (连载一)

简介:新监管形式下,数据的合规合理应用和数据安全是大家密切关注和探讨的话题点,而DataTrust隐私增强计算平台,能在保障数据隐私及安全前提下完成多方数据联合分析、联合训练、联合预测,实现数据价值流通,本…

查看系统是否安装了ftp服务器上,linux查看是否安装了ftp服务器上

linux查看是否安装了ftp服务器上 内容精选换一换安装Tomcat时启动失败。请按如下步骤查找原因并处理:对于已安装Tools的Linux弹性云服务器,升级内核前,需先卸载Tools,否则存在如下风险:升级内核后,Linux弹性…

掌握 Dowanward API 的妙用,轻松拿捏 kubernetes 环境变量

作者 | 江小南来源 | 江小南和他的小伙伴们引言前两天,公司有个新同事愁眉苦脸,看起来心事重重,我去问他怎么回事,原来是有个需求犯了难:一次部署起四个pod,每个pod名称还不一样,怎么判断是哪个…

一撕得:全员参与低代码开发,全面实现企业数字化管理

简介:借助钉钉宜搭,一撕得全面实现数字化管理,持续推动业务和企业进步。 北京一撕得物流技术有限公司 201-500人 / 互联网 / 中国-北京 / 数字化管理平台 “通过钉钉宜搭低代码技术,推进一撕得数字化转型。将日常办公及业务管理…

加码对象存储,XSKY星辰天合发布下一代对象存储XEOS V6

XSKY发布下一代对象存储XEOS V6,全新架构设计,具备“无限扩展”、“智能流动”、“多重保护”、“开放共赢”四大特性,进一步向主存储进军。 软件定义存储市场,即有传统存储大厂,也有更多优秀的国内存储厂商参与其中。…

引领新媒体时代的潮水方向—世相科技

漫步云端,世相科技正在引领新媒体时代的潮水方向。阿里云正在携手越来越多的新媒体客户,一道致力于简化基础设施与架构,提升更优的行业竞争力。 客户故事 新媒体的飞速发展,为各种创意传播带来了崭新机遇。世相科技子公司研发的中…

推文科技:AI解决方案助力内容出海

2017年,推文科技成立,推出业内针对网络文学的AI系统,助推网文批量出海。2018年,阿里云上线海外可用区,推文科技开始与阿里云合作。 创业宣言 创业是一件用行动去实践相信的事情,也许有一天,我…

多线程一定能优化程序性能吗?

作者 | 陆小风来源 | 码农的荒岛求生问:如果一个和尚挑水喝,两个和尚抬水喝,三个和尚没水喝,那么众人拾柴一定火焰高吗?多线程一定能提高程序性能吗?在计算机科学中,这个问题的标准答案是“it d…

4种常见分支模式解析及优劣对比

简介:团队研发的本质并不是团队规模越大,研发的效率就越高。我们以为团队规模越大,研发效率就会越高,可以做越多的东西,但是我们发现团队规模大到一定程度,整个研发效率是会下降的,甚至降得非常…

重构知识的供给模式 ——《数据平台》从思考到落地

简介:如何去建立一套 “高度自动化&体系化的知识管理系统,重构知识的供给模式”。是不是看不懂?而且有点冲?是不是谜语人附体?别急,本文作者将会做详细的说明。 作者 | 七惜 来源 | 阿里技术公众号 一…

PolarDB for PostgreSQL 内核解读 :HTAP架构介绍

简介:在 PolarDB 存储计算分离的架构基础上我们研发了基于共享存储的MPP架构步具备了 HTAP 的能力,对一套 TP的数据支持两套执行引擎:单机执行引擎用于处理高并发的 OLTP;MPP跨机分布式执行引擎用于复杂的 OLAP 查询,发…

kubernetes 的这几种存储卷,别再傻傻分不清了

作者 | 江小南来源 | 江小南和他的小伙伴们存储卷类型Kubernetes提供的存储卷(volume)属于Pod资源,共享于Pod内的所有容器,存储卷可在容器的文件系统之外存储相关的数据,也可以独立于Pod的生命周期实现数据持久化存储。…

这群人,用8年讲述体育能有多迷人

望尘科技:专注体育娱乐在线体验的自主研发,致力于让体育迷获得高品质的沉浸式体验。用科技致敬体育,是他们坚持的信仰。 客户故事 望尘科技一心专注深耕体育游戏。他们把自己的计算中心搬到了云上,借助阿里云数字基础设施为程序…

成中集团线下IDC迁移上云

阿里云根据成中集团业务场景入手,提供了上云方案和迁移建议,利用这套架构,保障了公司数据的安全性并且满足了公司对于备份机制的建立的基本诉求,并且降低了业务出现中断的风险。 公司介绍 成中简介: 我们公司是一家…

什么是hpaPaaS平台?

作者 | Gordon Van Huizen,Mendix公司平台战略高级副总裁 供稿 | Mendix Gartner为两种云端应用开发方法创造了两个名称:高生产力应用程序平台即服务(hpaPaaS)和高控制应用平台即服务(hcaPaaS)。本文将对二…

重新认识访问者模式:从实践到本质

简介:访问者模式在设计模式中的知名度虽然不如单例模式,但也是少数几个大家都能叫得上名字的设计模式了。不过因为访问者模式的复杂性,人们很少在应用系统中使用,经过本文的探索,我们一定会产生新的认识,发…

3个案例,详解如何选择合适的研发模式

简介:3个案例,详解如何选择合适的研发模式,研发模式的选择与产品形态、发布方式、团队规模、协作成熟度密切相关。本文我们将根据不同的团队场景,分析如何选择适合团队的研发模式。 策划&编辑|雅纯 上一讲&#x…

如何打造一款极速数据湖分析引擎

简介:本文向读者详细揭秘了数据湖分析引擎的关键技术,并通过 StarRocks 来帮助用户进一步理解系统的架构。 作者: 阿里云 EMR 开源大数据 OLAP 团队 StarRocks 社区数据湖分析团队 前言 随着数字产业化和产业数字化成为经济驱动的重要动…

如何在 Linux 命令行中按大小对文件进行排序

作者 | 刘光录来源 | TIAPls 命令用于显示目录的内容。使用 -l 选项,可以列出文件和目录及其属性。今天我们来分享一下如何根据文件大小对列表进行排序。ls -l 命令可以显示文件大小,但也仅仅是能让我们看到文件的大小,它默认是按照字母顺序显…