科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网网络频道UNIX操作系统的加锁解锁:等待事件及唤醒

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

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

加锁和解锁的基本思想是,当某个进程进入临界区,它将持有一个某种类型的锁(UNIX里一般来说是semaphore,Linux里一般是信号量和原子量或者spinlock)。

来源:chinaitlab 2007年12月27日

关键字: unix 系统安全

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共3页)

而在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()之后,就可以对资源加锁了,如(硬盘缓冲加锁、等待缓冲可用、唤醒等待进程):

//锁住bh
static inline void lock_buffer(struct buffer_head * bh)
{
    if (bh->b_lock)
        printk("hd.c: buffer multiply locked\n");
    bh->b_lock=1;
}
static inline void unlock_buffer(struct buffer_head * bh)
{
    if (!bh->b_lock)
        printk("hd.c: free buffer being unlocked\n");
    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 = %p\n",q);
            printk("       *q = %p\n",*q);
            printk("      tmp = %p\n",tmp);
            break;
        }
        tmp = tmp->next;
    } while (tmp != *q);
      }
    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章