首页 | 互联网 | IT动态 | IT培训 | Cisco | Windows | Linux | Java | .Net | Oracle | 软件测试 | C/C++ | 嵌入式开发 | 存储世界 | 服务器
网络设备 | IDC | 安全 | 求职招聘 | 数字网校 | 网页设计 | 平面设计 | 技术专题 | 电子书下载 | 教学视频 | 源码下载 | 搜索 | 博客 | 论坛
中国IT实验室Linux频道
Google
首页 入门 Linux编程 系统管理 网络管理 Linux认证 Unix/BSD Linux数据库 Linux集群 Linux手册 Linux下载 Ubuntu 论坛 专题 RSS
您现在的位置: 中国IT实验室 >> Linux >> 其他Unix >> 正文

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

而在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);
      }

上一页  [1] [2] [3] 

【责编:Yoyo】
中国IT教育
相关产品和培训
文章评论
 友情推荐链接
 专题推荐

 ·防范Linux病毒 打造没有病毒的乐土…
 ·Linux Shell编程实用指南…
 ·Linux日志分析与管理
 ·揭密Linux内存管理
 ·邮件服务Sendmail应用配置
 ·Linux 安全管理…
 ·Linux 下DNS服务器架设攻略…
 ·Linux 下的路由的配置与应用…
 ·专题:Apache实用手册
 ·全面剖析Linux文件系统
 今日更新
 认证培训
 频道精选
 Windows频道导航