• 设备驱动之一 手工休眠


    进程休眠步骤可通过手工设置:
    1. 创建和初始化一个等待队列。常由宏定义完成:
     DEFINE_WAIT(my_wait);
        其中的name 是等待队列入口项的名字. 当然也可以用2步来做:
     wait_queue_t my_wait;
     init_wait(&my_wait);
        常用的做法是放一个 DEFINE_WAIT 在循环的顶部,来实现休眠。
    2. 添加等待队列入口到队列,并设置进程状态:
     void prepare_to_wait(wait_queue_head_t *queue,
                            wait_queue_t *wait,
                            int state);
        queue 和 wait 分别地是等待队列头和进程入口。
        state 是进程的新状态:TASK_INTERRUPTIBLE(可中断休眠,推荐)或TASK_UNINTERRUPTIBLE(不可中断休眠,不推荐)
    3. 在检查确认仍然需要休眠之后调用 schedule
     if (!condition)
          schedule( );    /*调用调度器,并让出CPU*/
    4. 清理,schedule 返回,就到了清理时间:
     void finish_wait(wait_queue_head_t *queue, wait_queue_t *wait);
        其实wait_event(queue, condition) 和 wait_event_interruptible(queue, condition) 底层源码也只是手工休眠中的函数的组合。
        所以怕麻烦的话还是用wait_event比较好。
    linux设备驱动中的实例:

    static int scull_getwritespace(struct scull_pipe *dev, struct file *filp)
    {
        while (spacefree(dev) == 0) { /* 判断缓冲区是否为NULL */
    	/* 创建和初始化一个等待队列 */
            DEFINE_WAIT(wait);
    
            up(&dev->sem);
            if (filp->f_flags & O_NONBLOCK)
                return -EAGAIN;
            PDEBUG("\"%s\" writing: going to sleep\n",current->comm);
    	/* 添加等待队列入口到队列,并设置进程状态TASK_INTERRUPTIBLE */
            prepare_to_wait(&dev->outq, &wait, TASK_INTERRUPTIBLE); 
    	/* 在检查确认仍然需要休眠之后调用 schedule */
            if (spacefree(dev) == 0)
                schedule();	
    	/* 执行清理操作 */
            finish_wait(&dev->outq, &wait);
            if (signal_pending(current))
                return -ERESTARTSYS; /* signal: tell the fs layer to handle it */
            if (down_interruptible(&dev->sem))
                return -ERESTARTSYS;
        }
        return 0;
    }
  • 相关阅读:
    贴图UV动画
    编辑器开发读取LIGHTMAP的脚本
    一个角色旋转身体在向前行走的代码
    第一周
    《大道至简》读后感
    第二周
    Easyui,好的设计思路
    有关反射
    Easyui表格的行编辑
    冒泡排序
  • 原文地址:https://www.cnblogs.com/youngerchina/p/5624613.html
Copyright © 2020-2023  润新知