如果我们深入 <linux/wait.h>, 你见到在 wait_queue_head_t 类型后面的数据结构是非 常简单的; 它包含一个自旋锁和一个链表. 这个链表是一个等待队列入口, 它被声明做 wait_queue_t. 这个结构包含关于睡眠进程的信息和它想怎样被唤醒.

使一个进程睡眠的第一步常常是分配和初始化一个 wait_queue_t 结构, 随后将其添加到 正确的等待队列. 当所有东西都就位了, 负责唤醒工作的人就可以找到正确的进程.

下一步是设置进程的状态来标志它为睡眠. 在 <linux/sched.h> 中定义有几个任务状态. TASK_RUNNING 意思是进程能够运行, 尽管不必在任何特定的时刻在处理器上运行. 有 2 个状态指示一个进程是在睡眠: TASK_INTERRUPTIBLE 和 TASK_UNTINTERRUPTIBLE; 当然, 它们对应 2 类的睡眠. 其他的状态正常地和驱动编写者无关.

在 2.6 内核, 对于驱动代码通常不需要直接操作进程状态. 但是, 如果你需要这样做, 使用的代码是:

void set_current_state(int new_state); 在老的代码中, 你常常见到如此的东西: current->state = TASK_INTERRUPTIBLE;

但是象这样直接改变 current 是不鼓励的; 当数据结构改变时这样的代码会轻易地失效. 但是, 上面的代码确实展示了自己改变一个进程的当前状态不能使其睡眠. 通过改变 current 状态, 你已改变了调度器对待进程的方式, 但是你还未让出处理器.

放弃处理器是最后一步, 但是要首先做一件事: 你必须先检查你在睡眠的条件. 做这个检 查失败会引入一个竞争条件; 如果在你忙于上面的这个过程并且有其他的线程刚刚试图唤 醒你, 如果这个条件变为真会发生什么? 你可能错过唤醒并且睡眠超过你预想的时间. 因 此, 在睡眠的代码下面, 典型地你会见到下面的代码:

if (!condition) schedule();

通过在设置了进程状态后检查我们的条件, 我们涵盖了所有的可能的事件进展. 如果我们 在等待的条件已经在设置进程状态之前到来, 我们在这个检查中注意到并且不真正地睡眠. 如果之后发生了唤醒, 进程被置为可运行的不管是否我们已真正进入睡眠.

调用 schedule , 当然, 是引用调度器和让出 CPU 的方式. 无论何时你调用这个函数, 你是在告诉内核来考虑应当运行哪个进程并且转换控制到那个进程, 如果必要. 因此你从 不知道在 schedule 返回到你的代码会是多长时间.

在 if 测试和可能的调用 schedule (并从其返回)之后, 有些清理工作要做. 因为这个代 码不再想睡眠, 它必须保证任务状态被重置为 TASK_RUNNING. 如果代码只是从 schedule 返回, 这一步是不必要的; 那个函数不会返回直到进程处于可运行态. 如果由于不再需要 睡眠而对 schedule 的调用被跳过, 进程状态将不正确. 还有必要从等待队列中去除这个 进程, 否则它可能被多次唤醒.

linux一个进程如何睡眠的更多相关文章

  1. Linux进程的睡眠和唤醒简析

    COPY FROM:http://www.2cto.com/os/201204/127771.html 1 Linux进程的睡眠和唤醒 在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在 ...

  2. Linux进程的睡眠和唤醒

    1   Linux进程的睡眠和唤醒 在Linux中,仅等待CPU时间的进程称为就绪进程,它们被放置在一个运行队列中,一个就绪进程的状态标志位为TASK_RUNNING.一旦一个运行中的进程时间片用完, ...

  3. linux进程简单睡眠

    当一个进程睡眠, 它这样做以期望某些条件在以后会成真. 如我们之前注意到的, 任何睡 眠的进程必须在它再次醒来时检查来确保它在等待的条件真正为真. Linux 内核中睡眠的 最简单方式是一个宏定义, ...

  4. 【Android手机测试】linux内存管理 -- 一个进程占多少内存?四种计算方法:VSS/RSS/PSS/USS

    在Linux里面,一个进程占用的内存有不同种说法,可以是VSS/RSS/PSS/USS四种形式,这四种形式首字母分别是Virtual/Resident/Proportional/Unique的意思. ...

  5. Linux内存管理 一个进程究竟占用多少空间?-VSS/RSS/PSS/USS

    关键词:VSS.RSS.PSS.USS._mapcount.pte_present.mem_size_stats. 在Linux里面,一个进程占用的内存有不同种说法,可以是VSS/RSS/PSS/US ...

  6. Linux下一个进程可以开多少线程

    这个问题,整理了一下网上的资料,结果如下: 一.ulimit -n可以查看一个进程最多可以打开多少文件描述符数: 二.一个进程最多可以产生多少线程,可用如下的方法: 32位linux系统最大内存地址4 ...

  7. (转)如何在Linux中统计一个进程的线程数

    如何在Linux中统计一个进程的线程数 原文:http://os.51cto.com/art/201509/491728.htm 我正在运行一个程序,它在运行时会派生出多个线程.我想知道程序在运行时会 ...

  8. 操作系统复习——如何查看一个进程的详细信息,如何追踪一个进程的执行过程 ,如何在 Linux 系统下查看 CPU、内存、磁盘、IO、网卡情况?epoll和select区别?

    1. 如何查看一个进程的详细信息,如何追踪一个进程的执行过程 通过pstree命令(根据pid)进行查询进程内部当前运行了多少线程:# pstree -p 19135(进程号) 使用top命令查看(可 ...

  9. linux 下查看一个进程执行路径

    在linux下查看进程大家都会想到用 ps -ef|grep XXX 但是看到的不是全路径.怎么看全路径呢? 每一个进程启动之后在 /proc以下有一个于pid相应的路径 比如:ps -ef|grep ...

随机推荐

  1. shops

    #!/usr/bin/env python #coding:utf- import urllib2,sys,re,os,string reload(sys); sys.setdefaultencodi ...

  2. WinForm 实现主程序(exe)与其关联类库(*.dll)分开存放

    WinForm 实现主程序(exe)与其关联类库(*.dll)分开存放    开发环境:   Microsoft Windows 7 SP1 Microsoft.NET Framework 4.0 ( ...

  3. day39-Spring 08-Spring的AOP:基于AspectJ的注解

    基于AspectJ的注解的开发要重点掌握. 这些表达式肯定要应用在我们的某些个增强上. 学习AspectJ也是两种形式:一种是XML,一种是注解.AspectJ的增强,就是那些通知的类型.Aspect ...

  4. Django1.11使用命令makemigrations提示No Changes

    在项目中,遇到models模型变动,变动后合并发生问题,故当时做了删除应用文件夹下migrations文件,由于数据库里无较多新数据,故删除后重建,但重建后执行模型合并操作结果为No Changes, ...

  5. LRM-00109: could not open parameter file '/u01/app/oracle/product/12.1.0/db_1/dbs/initepps.ora'

    安装好oracle后,起动时报如下错误: [oracle@Oracle-A ~]$ export ORACLE_SID=ORCL [oracle@Oracle-A ~]$ sqlplus / as s ...

  6. Java Annotation入门

    Java Annotation入门作者:cleverpig 版权声明:本文可以自由转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明作者:cleverpig(作者的Blog:http:/ ...

  7. Django框架form表单配合ajax注册

    总结一下,其实form组件的主要功能如下: 生成页面可用的HTML标签 对用户提交的数据进行校验 保留上次输入内容 下面是写的登录页面的实例 1:views视图中的代码 # 注册页面 def regi ...

  8. @bzoj - 4356@ Ceoi2014 Wall

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给出一个N*M的网格图,有一些方格里面存在城市,其中首都位于网格 ...

  9. jq 监听返回事件

    <script> $(document).ready(function(e) {             var counter = 0;            if (window.hi ...

  10. oracle函数 ASCII(x1)

    [功能]:返回字符表达式最左端字符的ASCII 码值. [参数]:x1,字符表达式 [返回]:数值型 [示例] SQL> select ascii('A') A,ascii('a') a,asc ...