微波EDA网,见证研发工程师的成长!
首页 > 通信和网络 > 通信网络业界新闻 > UNIX操作系统的加锁解锁:等待事件及唤醒

UNIX操作系统的加锁解锁:等待事件及唤醒

时间:08-20 来源:赛迪网 点击:

这两个函数比较难以理解,主要是在最后两条语句。在schedule()之前,切换的是当前进程的上下文,但是,切换回来之后,却是将原先正在睡眠的进程置为就绪态。在执行schedule()之前,各指针如下图所示(不好意思,不会粘贴图片):

---| p | --- || / ---- Step 3 ---------| *p |--------->| current | ---- --------- | X Step 1 | / ---------------- Step 2 -----| Wait Process |<--------| tmp | ---------------- -----

而在schedule()返回到这段代码之后,事情就不一样了。因为在step 3之后,current进程已经进入睡眠,tmp指向的睡眠进程的描述符也被保存下来。从schedule()返回之后,执行的代码仍然是current,而tmp指向的仍然是wait process,此时将其状态置为就绪,等待下一次调度。

与前两个函数相比,wake_up相当简单:

//被唤醒的进程并不是马上投入运行,而是让其适合运行void wake_up(struct task_struct **p){ if (p && *p) { (**p).state=0; //将要唤醒的进程状态置为就绪 *p=NULL; //将进程移出等待的进程 }}

有了sleep_on()和wake_up()之后,就可以对资源加锁了,如(硬盘缓冲加锁、等待缓冲可用、唤醒等待进程):

//锁住bhstatic inline void lock_buffer(struct buffer_head * bh){ if (bh->b_lock) printk("hd.c: buffer multiply lockedn"); bh->b_lock=1;} static inline void unlock_buffer(struct buffer_head * bh){ if (!bh->b_lock) printk("hd.c: free buffer being unlockedn"); bh->b_lock=0; wake_up(&bh->b_wait);} static inline void wait_on_buffer(struct buffer_head * bh){ cli(); //禁止中断 while (bh->b_lock) sleep_on(&bh->b_wait); sti(); //恢复中断}//Linux 0.99.15的sleep和wake_up的实现(支持等待队列):static inline void __sleep_on(struct wait_queue **p, int state){ unsigned long flags; struct wait_queue wait = { current, NULL }; if (!p) return; if (current == task[0]) panic("task[0] trying to sleep"); current->state = state; add_wait_queue(p, &wait); //将当前进程加入等待队列 save_flags(flags); //保存中断掩码 sti(); //屏蔽中断 schedule(); //上下文切换 remove_wait_queue(p, &wait); //从等待队列中移除当前进程 restore_flags(flags); //恢复中断掩码}void wake_up(struct wait_queue **q){ struct wait_queue *tmp; struct task_struct * p; if (!q || !(tmp = *q)) return; do {//将等待队列中唤醒队首进程 if ((p = tmp->task) != NULL) { if ((p->state == TASK_UNINTERRUPTIBLE) || (p->state == TASK_INTERRUPTIBLE)) { p->state = TASK_RUNNING; if (p->counter > current->counter) need_resched = 1; } } if (!tmp->next) { printk("wait_queue is bad (eip = %08lx)n",((unsigned long *) q)[-1]); printk(" q = %pn",q); printk(" *q = %pn",*q); printk(" tmp = %pn",tmp); break; } tmp = tmp->next; } while (tmp != *q);}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top