现实中,很容易理解睡眠与唤醒的意思。这一概念如何应用到操作系统中的呢?首先明白睡眠与唤醒的“主体”是进程,也就是说进程睡眠与唤醒。其次需要了解什么”条件“导致其睡眠与唤醒。
1.Linux中进程睡眠含义与实现
睡眠的说法有很多,例如挂起,阻塞等,其实本质就是主体(进程)所处的一种状态,可以通过状态描述 TASK_INTERRUPTIBLE, TASK_UNINTERRUPTIBLE。 具体实现通过等待队列与运行队列(数据结构)来实现的,首先把进程标识为睡眠状态,其次添加到等待队列,最后从运行队列选择其他进程运行。

1)算法头文件
<linux/wait.h>

2)等待队列数据结构为:
wait_queue_head_t

3)等待队列的初始化
静态(编译时)初始化
DECLEAR_WAIT_QUEUE_HEAD(wqueue);

动态(运行时)初始化
wait_queue_head_t wqueue;
init_waitqueue_head(&wqueue)

4)添加到等待队列中
add_wait_queue(&video->waitq, &wait);

5)标记进程为睡眠状态
set_current_state(TASK_INTERRUPTIBLE);

6)自旋锁非常重要,主要保护条件“video->frames[video->first_clear_frame]->state != FRAME_CLEAR”并发访问,当两个进程被唤醒时,两个进程看到该条件成立,导致冲突。
spin_lock_irqsave(&video->spinlock, flags);

7)如果条件不成立,进行睡眠,从运行队列选择其他进程运行。
/* wait until video->first_clear_frame is really CLEAR */
 while (video->frames[video->first_clear_frame]->state != FRAME_CLEAR) {
    spin_unlock_irqrestore(&video->spinlock, flags);

        如果由于信号唤醒,那么首先从等待队列把进程删除,然后设置进程运行状态
        if (signal_pending(current)) {
            remove_wait_queue(&video->waitq, &wait);
                set_current_state(TASK_RUNNING);
                ret = -EINTR;
                goto out;
        }

        schedule();
        set_current_state(TASK_INTERRUPTIBLE);
        spin_lock_irqsave(&video->spinlock, flags);
}
spin_unlock_irqrestore(&video->spinlock, flags);

8)如果由于条件成立唤醒进程,首先从等待队列把进程删除,然后设置进程运行状态
remove_wait_queue(&video->waitq, &wait);
set_current_state(TASK_RUNNING);

2.Linux中进程唤醒含义与实现

Linux中进程唤醒就是从上述睡眠的等待队列中,把由于所有进程状态设置为运行,同时把起进程放入运行队列,将来某一时间,调度程序会选择运行此程序。

该程序会继续执行上面睡眠之后代码,即(7)(8).再次设置进程状态,从等待队列中删除。

唤醒函数接口非常简单:

wake_up_interruptible(&video->waitq);
Logo

更多推荐