Linux 内核睡眠的几种方式
译至:http://geeki.wordpress.com/2010/10/30/ways-of-sleeping-in-linux-kernel/
在Linux中睡眠有2-3种不同的方法。
睡眠的第一种简单的方法是将当前进程的状态设置为INTERRUPTIBLE或NON_INTERRUPTIBLE然后调用schedule。将进程设置为RUNNING之外状态很重要,因为只有这样,内核会将进程移出运行队列。进程被调度出去后,它需要以某种方式被调度回来 - 用wake_up()来实现。 这需要进程的task_struct中作为参数。 下面是一段来自Linux Journal的示例代码段:
[cpp] view plaincopy
- //Process A:
- spin_lock(&list_lock);
- if(list_empty(&list_head)) {
- spin_unlock(&list_lock);
- set_current_state(TASK_INTERRUPTIBLE);
- schedule();
- spin_lock(&list_lock);
- }
- /* Rest of the code ... */
- spin_unlock(&list_lock);
- //Process B:
- spin_lock(&list_lock);
- list_add_tail(&list_head, new_node);
- spin_unlock(&list_lock);
- wake_up_process(processA_task);
上面的一段代码会导致一个“无效唤醒”的竞争条件问题。 说明如下:该进程对一些条件检查,然后设置任务状态为可中断并进入睡眠。 这时可能有一个小的竞争条件,当满足该条件的进程在条件检查之后唤醒睡眠进程时(唤醒任务仅仅是将任务状态设置成RUNNING,并将它保持在运行队列) - 这会导致一种情况:睡眠进程在唤醒进程将其唤醒后进入睡眠 - 这就是无效唤醒的问题。 这样做的后果可能会很严重也可能并不严重。 如果睡眠进程将条件标记为假,然后继续睡眠,那么这个无效唤醒的问题将导致睡眠进程永远保持该状态。 但是,如果条件是通过外部满足的话,那么最终条件将变为真,唤醒进程将唤醒睡眠进程。 这种情况的解决方法是在检查前设置任务状态 - 因此,如果这个进程进入睡眠状态,那么它将保持在运行队列而不是等待队列。 如果任务状态是running的话,schedule() API将保持进程只在运行队列。
还有一个问题,这种形式的睡眠要求waker进程中必须知道睡眠进程的task_struct。当存在一个以上的睡眠进程时这可能令人厌倦。 因此,在内核中睡眠的另一种形式是使用等待队列。 下面是一个示例一段代码,声明了一个等待队列,并把自己保持在等待队列。
[cpp] view plaincopy
- DECLARE_WAIT_QUEUE_HEAD(my_event);
- wait_event_interruptible(my_event, (cond == x));
- void my_wake_up(void)
- {
- if (cond == x)
- return;
- set_bit(2, &my_flags);
- wake_up_interruptible(&my_event);
- }
正如在上面这段代码中可以看出,当我们在一个队列中等待时,我们也传递了一个条件用于检查 - 这样内核在将进程保持在等待队列之前要确保这个条件不为真。内核将改变进程的状态,然后检查条件,并把该进程中加入等待队列。 当时间到时,waker进程将来唤醒等待队列上进程 - 这样,它不需要知道哪些进程正在睡眠,它只需知道等待队列。 在一定程度上比之前的不可扩展的睡眠形式更好。 还有一个API,wake_up_all(),将唤醒所有的进程 - 这个API如果不能正确使用会导致惊群问题。 不过,也有这个API的相关使用场景- 例如,多个读者和一个写者的问题可以使用这个API - 当写者已经获得了锁,所有的读者都被放在等待队列 - 当写者完成后,它可以用wake_up_all()唤醒在等待队列中的所有进程。 所有的读者会成功获得锁。
睡觉的另一种方法是睡眠一定的时间段。 进程可以以jiffies或毫秒/秒形式睡眠。 下面是以毫秒形式睡眠的示例代码。
[cpp] view plaincopy
- read_done = 0;
- while (read_done == 0) {
- msleep(2); //sleep for a couple of milliseconds.
- }
- // Another thread
- read_done = 1;
这个进程不知道它要花多少时间,但是它确保不会需要很长时间 - 因此它选择了避免创建另一个等待队列,而是简单地使用msleep()API来睡2毫秒。 迟早,条件变成真然后进程会继续处理。这带来上下文切换等方面的一些小的CPU开销,但它是一个简单的设计。 顺便说一句,如果我们想用jiffies睡眠的话,可以使用schedule_timeout()API。 它的内部处理是,把进程加入了某个等待队列,然后到了时间后唤醒它。 msleep()也是做同样的事情。
Linux 内核睡眠的几种方式的更多相关文章
- linux内核debug的一种方式:procfs
#include <linux/module.h> #include <linux/compat.h> #include <linux/types.h> #incl ...
- linux内核睡眠状态解析
1. 系统睡眠状态 睡眠状态是整个系统的全局低功耗状态,在这种状态下,用户空间的代码不能被执行并且整个系统的活动明显被降低 1.1 被支持的睡眠状态 取决于所运行平台的能力和配置选项,Linux内核能 ...
- 设置 Linux 下打印机的几种方式
设置 Linux 下打印机的几种方式 一.使用 cups 进行设置 如若遇到 cups 也没有驱动的话可以前往 openprinting.org 找寻对应驱动. 二.前往 official 下载驱动 ...
- linux创建文件的四种方式(其实是两种,强行4种)
linux创建文件的四种方式: 1.vi newfilename->i->编辑文件->ESC->:wq! 2.touch newfilename 3.cp sourcePath ...
- Linux 软件安装的三种方式
Linux 软件安装的三种方式 1.yum 语法格式: yum -y install package.name -y yes # 遇到提示自动输入yes 案例: 安装ifconfig命 ...
- Linux 安装 Nodejs 的两种方式
Linux 安装 Nodejs 的两种方式 目录 Linux 安装 Nodejs 的两种方式 一.压缩包安装 Nodejs 二.源码编译安装 Nodejs 一.压缩包安装 Nodejs 下载 Node ...
- Linux下定时执行任务的几种方式
如果说我说如果,你的某一个目录下会经常的生成一些垃圾文件,比如访问日志.错误日志.core文件,而你又不想过几分钟就去手动检查一下,那么可以使用定时执行任务的方式来解决.目前我所知道的可以执行定时任务 ...
- linux异步IO的两种方式【转】
转自:https://blog.csdn.net/shixin_0125/article/details/78898146 知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个C ...
- Linux内核替换的一种简单方法
前言 使用现有centos的镜像,在海光机器上出现了无法运行的情况,grub引导后就只剩下光标一直在闪,无任何字符输出.这种情况大概率是因为Linux的内核无法运行在海光的CPU上所导致的. 已得知L ...
随机推荐
- 03丨认识文档数据库MongoDB
- nginx反向代理网站镜像
某些公司会墙特定网站,如果你有一个可访问的域名和服务器,就可以通过nginx反向代理来来解决这些问题.比如现在我们用mirror.example.com镜像www.baidu.com,以下是详细操作. ...
- 路由信息相关 route 网卡
目录 route命令 1.查看路由表 2.管理路由 基本网络配置 添加网卡地址 修改网卡UUID route命令 路由表管理命令,路由表主要构成: Destination: 目标网络ID,表示可以到达 ...
- 字符串算法(string_algorithm)
format 作用 格式化输出对象,可以不改变流输出状态实现类似于printf()的输出 头文件 #include <boost/format.hpp> using namespace b ...
- IDEA 通过ctrl+滚轮缩放字体大小
能用图解决的问题,尽量简单粗暴通俗易懂 1.第一种方式 2.第二种方式
- Python+Selenium学习笔记15 - 读取txt和csv文件
读取txt的内容并用百度查找搜索 1 # coding = utf-8 2 3 from selenium import webdriver 4 import time 5 6 # 打开浏览器 7 d ...
- C# MVC(File)控件多张图片上传加预览
刚来公司实习,老板叫我写一个积分商城网站.用的是公司的框架结构搭建的后台,所以后台的图片上传不需要自己写.但是前台的评价图片就需要自己手写了,在网上找了很多代码发现都用不了.问了很多人也都没有实现! ...
- 如何挑选深度学习 GPU?
如何挑选深度学习 GPU? 深度学习是一个对计算有着大量需求的领域,从一定程度上来说,GPU的选择将从根本上决定深度学习的体验.因此,选择购买合适的GPU是一项非常重要的决策.那么2020年,如何选择 ...
- Velodyne VLP-16激光雷达数据分析
Velodyne VLP-16激光雷达数据分析 Velodyne VLP-16激光雷达保持了 Velodyne 在 LiDAR 中的突破性重要功能:实时收发数据.360 度全覆盖.3D 距离测量以及校 ...
- 基于ARM Cortex-M的SoC存储体系结构和实战
基于ARM Cortex-M的SoC存储体系结构和实战 System on Chip Architecture Tutorial Memory Architecture for ARM Cortex- ...