免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3141 | 回复: 5
打印 上一主题 下一主题

任务等待操作sleep_on [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-09-07 11:47 |只看该作者 |倒序浏览
本帖最后由 nathan10 于 2010-09-07 11:49 编辑
  1. static inline void __sleep_on(struct task_struct **p, int state)
  2. {
  3.         struct task_struct *tmp;
  4.         unsigned int flags;

  5.         if (!p)
  6.                 return;
  7.         if (current == &(init_task.task))
  8.                 panic("task[0] trying to sleep");
  9.         __asm__("pushfl ; popl %0":"=r" (flags));
  10.         tmp = *p;
  11.         *p = current;
  12.         current->state = state;
  13. /* make sure interrupts are enabled: there should be no more races here */
  14.         sti();
  15. repeat:        schedule();
  16.         if (*p && *p != current) {
  17.                 current->state = TASK_UNINTERRUPTIBLE;
  18.                 (**p).state = 0;
  19.                 goto repeat;
  20.         }
  21.         if (*p = tmp)
  22.                 tmp->state=0;
  23.         __asm__("pushl %0 ; popfl"::"r" (flags));
  24. }
复制代码
上述代码repeat位置执行任务调度schedule()后,为何一定在当前这个等待任务*P被唤醒以后,调度程序才返回这里,并继续向下执行?这里我遗漏了什么吗?
百思不得其解。。。请教,谢谢

论坛徽章:
0
2 [报告]
发表于 2010-09-07 12:58 |只看该作者
因为这里是让进程睡眠... 等待某个特定的事件...有TASK_INTERRUPTABLE和TASK_UNINTERRUPTABLE两种睡眠方式...
    在这个函数里. 将进程状态改变为这两个之一之后再执行schedule()函数就会重新调度...
    而在调度进程的时候... 会将状态为TASK_INTERRUPTABLE且有pending信号到来的进程状态改为
  TASK_RUNNING... 然后再计算所有处于TASK_RUNNING的goodness...最后选择一个进程运行...
   所以要这个进程被唤醒之后... 且! 被调度运行... 才能返回到repeat标号处...
   
   为何回到这里...就是进程切换的问题啦... 总之会保持进程执行的连续性...

论坛徽章:
0
3 [报告]
发表于 2010-09-07 14:11 |只看该作者
回复 2# PCliangtao


    谢谢你的回复,但我还是不明白。我是这样想的,sleep_on函数可能是任务A执行的睡眠操作,当A成为不可中断睡眠状态时,下面的schedule()函数重新调度任务,可能调度了B开始执行。
并在最后通过switch_to函数切换到任务B。这么一来,schedule函数执行完毕,current也指向了当前任务B。然后顺利往下执行sleep_on中的以下语句。做检查(*p && *p != current)。明显这里*p是不等于current的。*p指向A,current指向B。而不满足条件,就会current->state = TASK_UNINTERRUPTIBLE。也就是立马把B从就绪放到了不可中断睡眠状态。。

我上面理解有什么问题没?我就是纠结在这一个过程中了。而看到的资料都说是,必须在schedule函数调度了A后,才会返回到sleep_on函数中,并继续向下执行(当然这样看的话,程序后面也好理解)。但是我就理解不了shcedule如何能在这里等待着等待着调度A。直到A被调度为止。毕竟A刚被置成了不可中断睡眠状态。

希望您能帮助我解开上面的问题所在,不胜感激。谢谢

论坛徽章:
0
4 [报告]
发表于 2010-09-07 14:55 |只看该作者
回复 3# nathan10


    我的粗浅认识:
schedule函数执行后,如果执行进程B,肯定不会返回到schedule()函数后执行。因为,如果执行进程B,CS:IP里面放的是进程B的地址。

论坛徽章:
0
5 [报告]
发表于 2010-09-07 16:08 |只看该作者
回复 4# omycle

呵呵,上面我终于苦思明白了。。
schedule()函数调度B确实是不会返回到sleep_on的。但是如果A等待的资源释放了,那么A任务就会得到唤醒,由wake_up做,而且wake_up只对这一资源的等待列表的第一个任务做wake_up,其他的由任务之间嵌套的激活成就绪状态。

这里的关键就是任务切换,即schedule最后的switch_to函数,这个函数完成了sleep_on函数中当前被设置成不可中断睡眠状态的任务A与schedule调度的新任务X之间的状态的切换。
这里原来的“当前任务”即A执行到了sleep_on函数中的schedule下一句,因此A的EIP内也保存了这个地址。。。当后面的某一个机会里,任务A被再次调度的时候,它的状态信息被重新加载进来。这样,就可以依据EIP找到曾今执行停下来的位置(这里就是schedule函数后一句),然后继续往下执行。

所以资料上在这里,都说是必须等当前任务A被唤醒时,调度程序才会回到这个函数中来。。

以上请不吝赐教

论坛徽章:
0
6 [报告]
发表于 2010-09-07 16:51 |只看该作者
恩... 关键要理解schedule()函数里所执行的swtich的作用...也就是进程切换... 操作系统里多任务是怎样实现的...  这里不能按照通常的C语言里的顺序执行来理解...
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP