xv6 中的一些系统调用(下)

〇、前言

本文将会结合源代码谈论 sleepwakeup 这两个系统调用。

一、sleep()系统调用

以下是sleep()函数源码:

// Atomically release lock and sleep on chan.
// Reacquires lock when awakened.
void
sleep(void *chan, struct spinlock *lk)
{struct proc *p = myproc();// Must acquire p->lock in order to// change p->state and then call sched.// Once we hold p->lock, we can be// guaranteed that we won't miss any wakeup// (wakeup locks p->lock),// so it's okay to release lk.acquire(&p->lock);  //DOC: sleeplock1release(lk);// Go to sleep.p->chan = chan;p->state = SLEEPING;sched();// Tidy up.p->chan = 0;// Reacquire original lock.release(&p->lock);acquire(lk);
}

先来看看 lost wakeup 问题。当一个进程在 sleep() 时,如果 sleep() 了一半,状态还没来得及修改为SLEEPING,这时候发生了中断,并且被某些进程调用了 wakeup(),那么这个 wakeup()肯定不能把这个进程唤醒。而且,在被中断恢复后,它将永远等不到唤醒,因为唤醒已经错过。所以,在这里必须要正不可中断性操作先后性。因为在下面就会看到 wakeup() 只唤醒状态为 SLEEPING 的进程。

因此我们必须保证,sleep() 是一个原子操作,在 sleep() 执行过程中,要么执行完全,要么没有被执行。所以这里必须加一个进程锁。所以在下面就会看到 wakeup() 中也会尝试获取休眠的进程锁。

在持有进程锁的时候,将进程的状态设置为 SLEEPING 并记录sleep channel,之后再调用 sched() 函数,这个函数中会再调用 swtch() 函数(而这会返回到 scheduler()函数中),此时 sleep() 函数中仍然持有了进程的锁,wakeup() 仍然不能做任何事情。

因此在 sleep()之后,这个锁必须释放。我们来看看细节:

void
scheduler(void)
{...swtch(&c->context, &p->context);// Process is done running for now.// It should have changed its p->state before coming back.c->proc = 0; // 返回的位置,此刻继续执行}release(&p->lock);...
}

在这里,它会继续执行上一次执行到的位置,即 c->proc = 0,然后执行 release(&p->lock),也就是释放锁,而且释放的是 sleep() 中的当前进程的锁。(这一点不是很好理解,可以理解为用的上一个进程的代码释放当前进程的锁?总之,这些代码就冰冷冷的放在内存里,被 pc 不断地指一遍又一遍)。更有意思的是,在 sched() 函数返回之后,继续运行:

void
sleep(void *chan, struct spinlock *lk)
{...sched();// Tidy up.p->chan = 0; // 就绪执行的位置// Reacquire original lock.release(&p->lock);acquire(lk);
}

这里 release(&p->lock) 实际上释放的是 scheduler() 中选中的进程的锁。

所以在调度器线程释放进程锁之后,wakeup() 才能终于获取进程的锁,发现它正在 SLEEPING状态,并唤醒它。

这里的效果是由之前定义的一些规则确保的,这些规则包括了:

  • 调用 sleep 时需要持有condition lock,这样 sleep 函数才能知道相应的锁;
  • sleep函数只有在获取到进程的锁 p->lock之后,才能释放 condition lock
  • wakeup需要同时持有两个锁才能查看进程。

二、wakeup()调用

以下是 wakeup() 的源码:

// Wake up all processes sleeping on chan.
// Must be called without any p->lock.
void
wakeup(void *chan)
{struct proc *p;for(p = proc; p < &proc[NPROC]; p++) {if(p != myproc()){acquire(&p->lock);if(p->state == SLEEPING && p->chan == chan) {p->state = RUNNABLE;}release(&p->lock);}}
}

可以看到它的工作很简单,检查两个条件之后,就修改进程的状态为 RUNNABLE

三、总结

这篇文章详细地介绍了 xv6 操作系统中的 sleep()wakeup() 系统调用的实现原理以及相关的内部工作机制。主要强调了在 sleep() 中的原子操作性,确保了操作的完整性,以及在 wakeup() 中唤醒休眠进程的方式。

关于 sleep()

强调了 sleep() 操作的原子性,使用进程锁确保 sleep() 操作是一个原子操作,避免了 “lost wakeup” 问题的发生。
通过释放持有的锁,让出 CPU 控制权,进入 SLEEPING 状态,然后释放进程锁,使得其他进程能够继续运行。
调度器在合适的时机恢复了进程的执行,完成 sleep() 操作。

关于 wakeup()

wakeup() 通过遍历进程列表,并获取每个进程的锁,查看处于 SLEEPING 状态且 sleep channel 匹配的进程,将其状态设置为 RUNNABLE,唤醒进程。

整体上,这篇文章清晰地解释了 sleep()wakeup() 这两个关键系统调用的工作原理和实现细节,突出了在并发环境下确保原子性操作和避免死锁的重要性。

全文完,感谢阅读。

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

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

相关文章

无线且列窄图片如何转excel?

写此文原因&#xff1a;图片要转excel&#xff0c;这放以前&#xff0c;是不能实现的功能&#xff0c;但随着人工智能的蓬勃发展&#xff0c;人们已克服了这一难题&#xff0c;但是&#xff0c;我们知道&#xff0c;要将图片识别成excel&#xff0c;识别程序首先要先识别图片中…

如何在小米路由器4A千兆版刷入OpenWRT并通过内网穿透工具实现公网远程访问

文章目录 前言1. 安装Python和需要的库2. 使用 OpenWRTInvasion 破解路由器3. 备份当前分区并刷入新的Breed4. 安装cpolar内网穿透4.1 注册账号4.2 下载cpolar客户端4.3 登录cpolar web ui管理界面4.4 创建公网地址 5. 固定公网地址访问 前言 OpenWRT是一个高度模块化、高度自…

交易历史记录20231206 记录

昨日回顾&#xff1a; select top 10000 * from dbo.CODEINFO A left join dbo.全部&#xff21;股20231206010101 B ON A.CODE B.代码 left join dbo.全部&#xff21;股20231206CONF D on A.CODED.代码left join dbo.全部&#xff21;股20231206 G on A.CODEG.代码 left…

解决前端跨域问题,后端解决方法

Spring CloudVue前后端分离项目报错&#xff1a;Network Error&#xff1b;net::ERR_FAILED&#xff08;请求跨越&#xff09;-CSDN博客记录自用

Kafka-快速实战

Kafka介绍 ChatGPT对于Apache Kafka的介绍&#xff1a; Apache Kafka是一个分布式流处理平台&#xff0c;最初由LinkedIn开发并于2011年开源。它主要用于解决大规模数据的实时流式处理和数据管道问题。 Kafka是一个分布式的发布-订阅消息系统&#xff0c;可以快速地处理高吞吐…

阿里云国际基于CentOS系统镜像快速部署Apache服务

阿里云轻量应用服务器提供了Windows Server系统镜像和主流的Linux系统镜像&#xff0c;您可以通过该类镜像创建纯净、安全、稳定的运行环境。本文以CentOS 7.6系统镜像为例&#xff0c;介绍如何快速配置Apache服务。 背景信息 注意&#xff0c;阿里云国际通过corebyt注册并充…

使用rawpy.imread读取.RAW格式数据和.dng格式数据(附代码)

.dng格式是一个更兼容、更高效的RAW格式。如果需要在不同软件之间交换RAW文件&#xff0c;或者需要在软件中进行大量编辑&#xff0c;那么.dng格式是一个不错的选择。 目录 一、 .dng格式数据和.RAW格式数据二、 .dng格式数据和.RAW格式数据区别三、安装rawpy包四、读取.dng格式…

Flask应用基础入门总结

【1】使用migrate方式进行数据库连接 使用migrate方式进行数据库连接需要在终端分别运行三行代码&#xff1a; #init&#xff08;运行一次即可&#xff09;&#xff08;此db为自己设置的连接数据库的对象,可以修改&#xff09; flask db init #&#xff08;将orm模型生成迁移…

从零开始搭建企业管理系统(四):集成 Knife4j

集成 Knife4j 前言Knife4j是什么集成 Knife4j引入 pom 依赖添加基础配置启动程序测试完善文档信息编写配置类修改 UserController修改 UserEntity修改 BaseEntity 文档效果图swagger 界面knife4j 界面 前言 前面一小节我们使用postman来进行接口的调试&#xff0c;如果接口一多…

游戏王的题解

目录 原题&#xff1a; 时间&#xff1a;1s 空间&#xff1a;256M 题目描述 输入格式 输出格式 样例输入 样例输出 题目大意&#xff1a; 主要思路&#xff1a; dp转移&#xff1a; dp初始化&#xff1a; 代码&#xff1a; 原题&#xff1a; 时间&#xff1a;1s …

springboot集成knife4j详细教程

使用原生的swagger作为接口文档&#xff0c;功能不够强大&#xff0c;并且默认的ui比较简陋&#xff0c;不符合大众审美。所以实际开发中推荐使用knife4j对swagger进行增强。knife4j的地址&#xff1a;https://gitee.com/xiaoym/knife4j 基本使用 想要使用knife4j非常简单&…

深入学习Redis:从入门到实战

Redis快速入门 1.初识Redis1.1.认识NoSQL1.1.1.结构化与非结构化1.1.2.关联和非关联1.1.3.查询方式1.1.4.事务1.1.5.总结 1.2.认识Redis1.3.安装Redis1.3.1.依赖库1.3.2.上传安装包并解压1.3.3.启动1.3.4.默认启动1.3.5.指定配置启动1.3.6.开机自启 1.4.Redis桌面客户端1.4.1.R…

【VS Code开发】使用Live Server搭建MENJA小游戏并发布至公网远程访问

文章目录 前言1. 编写MENJA小游戏2. 安装cpolar内网穿透3. 配置MENJA小游戏公网访问地址4. 实现公网访问MENJA小游戏5. 固定MENJA小游戏公网地址 前言 本篇教程&#xff0c;我们将通过VS Code实现远程开发MENJA小游戏&#xff0c;并通过cpolar内网穿透发布到公网&#xff0c;分…

C++ //习题3.8 写出下面各逻辑表达式的值。设a=3,b=4,c=5。

C程序设计 &#xff08;第三版&#xff09; 谭浩强 习题3.8 习题3.8 写出下面各逻辑表达式的值。设a3&#xff0c;b4&#xff0c;c5。 (1) a b > c && b c (2) a || b c && b - c (3) !(a > b) && !c || 1 (4) !(x a) && (y b…

FastAPI之响应状态码

使用FastAPI自定义响应状态码 FastAPI 是一个现代、快速的 web 框架&#xff0c;用于构建API服务&#xff0c;它允许你通过Python 3.6及以上版本进行编程。一个重要的API设计是返回合适的响应状态码&#xff0c;这可以使得客户端理解服务端的处理结果。本教程将向你展示如何在…

推出 Amazon EC2 C7i 实例

亚马逊云科技宣布全面推出由定制的第 4 代英特尔至强可扩展处理器&#xff08;代号为 Sapphire Rapids&#xff09;提供支持的 Amazon Elastic Compute Cloud (Amazon EC2) C7i 实例。这些定制处理器仅在亚马逊云科技上可用&#xff0c;与其他云提供商使用的基于 x86 的同类英特…

Kafka事务是怎么实现的?Kafka事务消息原理详解

目录 一、Kafka事务性消息1.1 介绍Kafka事务性消息1.2 事务性消息的应用场景1.3 Kafka事务性消息的优势 二、Kafka事务性消息的使用2.1 配置Kafka以支持事务性消息生产者配置消费者配置 2.2 生产者&#xff1a;发送事务性消息创建Kafka生产者开始事务发送消息提交或中止事务 2.…

logstash之grok插件自定义规则学习

文章目录 1、前言2、Grok提供的常用Patterns说明及举例2.1 常用的表达式说明 3、使用grok插件进行日志字段处理4、案例1&#xff1a;处理nginx的日志4.1、查看nginx日志格式4.2、对nginx的日志进行过滤处理 5、案例2&#xff1a;处理tomcat的日志5.1、[安装logstash-filter-mul…

外包干了3个月,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…