liunx内核睡眠机制

一,手动睡眠
        使用灵活
二,简单睡眠
        使用简单

简单睡眠的实现:
 <linux/sched.h>
1,定义等待队列头
    wait_queue_head_t    readq;
2,初始化等待队列头
    init_waitqueue_head(wait_queue_head_t *);
    例如:  init_waitqueue_head(&readq);
    注意:这个操作不能省略,且必须在第一次使用等待队列之前初始化,否则后果严重
3,睡眠---等待事件
        等待队列:分为排他式睡眠,不排它式睡眠。
        wait_event(wait_queue_head_t , condition );
        condition:是一个表达式      唤醒条件(条件为真唤醒,为假继续睡)
           睡前:
             真     不睡
            假       睡
         醒后:
            真    醒
            假    继续睡
4,唤醒
    wake_up(wati_queue_head_t *)
    例如:wake_up(&readq);
       
  手动睡眠实现:
  <linux/sched.h>
  1、定义等待队列头
      wait_queue_head_t readq;
  2、初始化等待队列头
      init_waitqueue_head(wait_queue_head_t *);
      例:init_waitqueue_head(&readq);
      注意:这个操作不能省,且必须在第一次使用等待队列之前初始化,否则后果严重
  3、睡眠
    1) 定义等待队列节点
    2) 如果是可中断睡眠判断是否有信号产生
    3) 将等待队列节点与当前进程关联
    4) 将节点挂载队列头上
    5) 设置当前进程状态为睡眠态
    6) 调用schedule()函数,主动产生调度,因为当前进程状态为睡眠态,所以系统不会对当前进程产生调度----睡眠
    7) 被唤醒后做好下一次睡眠的准备,并确认是否需要继续睡
    8) 设置进程状态为运行态
    9) 移除节点
     

   4、唤醒
      wake_up(wait_queue_head_t *)

  二、非阻塞
    非阻塞的实现是通过判断file->f_flags 对应的O_NONBLOCK是否置位来决定

    read(struct file *file, ....)
    {
      if(不可读)  {
        if(file->f_flags & O_NONBLOCK) {
          return -EAGAIN;
      }
      wait_event();
    }



三,多路复用
    liunx/...h    linux操作系统
    asm/....h    通用
    plat/....h    品牌
    mach/...h    平台
    应用层:
    select
    |
    |
    flie_operations->poll
    {
        1,将当前驱动的等待队列与当前进程关连
            poll_wait
        2,判断设备的状态返回给上层
    }
  例:
      static unsigned int xxx_poll(struct file *filp, poll_table *wait)
      {
          unsigned int mask = 0;
         
          ...  
          poll_wait(filp, r_wait, wait);//加读等待队列头
          poll_wait(filp, w_wait, wait);//加写等待队列头

          if (...)//可读
          {
            mask |= POLLIN | POLLRDNORM; /*标示数据可获得*/
          }  

          if (...)//可写
          {
            mask |= POLLOUT | POLLWRNORM; /*标示数据可写入*/
          }
          ...

          return mask;
      }
  四、异步通知
    应用程序:
        singal(SIGIO, handler);
        /*设置文件描述符的属主*/
        fcntl(fd, F_SETOWN, getpid());
              file->f_owner<====getpid()

        /*打开异步模式*/
        int oflags = fcntl(fd, F_GETFL);
            oflags = file->f_flags
        fcntl(fd, F_SETFL, oflags | FASYNC);
            oflags |= FASYNC

        当打开异步模式的时候驱动中file_operations->fasync方法会被调用
   
    驱动实现:
      1、定义异步结构
          struct fasync_struct *mystruct;
      2、实现file_operations->fasync(int fd, struct file *file, int on)
        说明:on 0  <==== file->f_flags & ~FASYNC
                 1  <==== file->f_flags | FASYNC
          return fasync_helper(fd, file, on, &mystruct)
      3、在合适的位置发送信号
        kill_fasync(&mystruct, SIGIO, POLL_IN);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_27205523

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值