免费注册 查看新帖 |

Chinaunix

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

[进程管理] 想不明白的一个进程调度问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-12-08 15:18 |只看该作者 |倒序浏览
内核中经常有set_current_state(TASK_INTERRUPTIBLE);这段代码,并且还没有放入唤醒队列中(例如2.6.18中的do_poll函数),当执行完这段代码之后:
1.此时刚好时间片到期,那此进程是不是永远不会执行了?
2.此事发生抢占,会出现什么情况?

另外,内核中有preempt_schedule函数,这个函数中
                add_preempt_count_notrace(PREEMPT_ACTIVE);
                schedule();
                sub_preempt_count_notrace(PREEMPT_ACTIVE);
当schedule返回后,进程已经切换,此时 sub_preempt_count_notrace的是另一个进程的preempt???

论坛徽章:
0
2 [报告]
发表于 2011-12-08 16:23 |只看该作者
内核中经常有set_current_state(TASK_INTERRUPTIBLE);这段代码,并且还没有放入唤醒队列中(例如2.6.18中的do_poll函数),当执行完这段代码之后:
1.此时刚好时间片到期,那此进程是不是永远不会执行了?
2.此事发生抢占,会出现什么情况?

另外,内核中有preempt_schedule函数,这个函数中
                add_preempt_count_notrace(PREEMPT_ACTIVE);
                schedule();
                sub_preempt_count_notrace(PREEMPT_ACTIVE);
当schedule返回后,进程已经切换,此时 sub_preempt_count_notrace的是另一个进程的preempt???

1.第一个问题不怎么懂,但你的看了你的列子
          poll_initwait(&table);
        fdcount = do_poll(nfds, head, &table, end_time);
        poll_freewait(&table);
应该和do_poll的前后两个函数有关。
2.这个首先应该不是 “sub_preempt_count_notrace的是另一个进程的preempt”   当schedule()返回后,仍然在原进程中。
preempt_active在内核里解释的很清楚,当进行内核抢占时的标志。

论坛徽章:
0
3 [报告]
发表于 2011-12-08 16:39 |只看该作者
本帖最后由 yifei429 于 2011-12-08 16:44 编辑

回复 2# mihouge
1. 第一个问题我想问的是时间片到了之后会设置set_tsk_need_resched;但此时进程状态不是running,还会被调度回来么?
函数schedule中有
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
..........
deactivate_task(rq, prev, DEQUEUE_SLEEP);
}
不就把当前进程踢出去了么?

2. preempt_schedule中,为什么schedule之后还是原进程?那抢占的优先级高的进程没有得到执行?

论坛徽章:
0
4 [报告]
发表于 2011-12-08 16:58 |只看该作者
preempt_schedule中,为什么schedule之后还是原进程?那抢占的优先级高的进程没有得到执行?
yifei429 发表于 2011-12-08 16:39



    下班没时间看第一个问题了
第二个问题是这样的
你的进程A先调用add_preempt_count_notrace(PREEMPT_ACTIVE);
然后调用schedule(),该进程A放弃了对CPU的占用,进程A处于运行队列或者休眠队列中。CPU执行别的进程的语句了。
过了一段时间之后,等到再度调度到你的进程A,这时,你的进程A又一次占用到了CPU,就从上次断掉的地方开始执行,也就是开始执行sub_preempt_count_notrace(PREEMPT_ACTIVE);

论坛徽章:
0
5 [报告]
发表于 2011-12-08 17:16 |只看该作者
下班没时间看第一个问题了
第二个问题是这样的
你的进程A先调用add_preempt_count_notrace(PRE ...
azzurris 发表于 2011-12-08 16:58



    那也就是说preempt_schedule是在第一个进程中调用的?调用点再第一个进程中?

论坛徽章:
0
6 [报告]
发表于 2011-12-08 17:43 |只看该作者
回复 4# azzurris

第一个问题就是问,当一个进程调用set_current_state(TASK_INTERRUPTIBLE);之后,刚好时间片用完,此时会发生什么情况?
时间片用完后,时钟中断会调用schedule吧,此时schedule因为该进程不是running,会不会把该进程踢出去,从而该进程永远不会被执行。

论坛徽章:
0
7 [报告]
发表于 2011-12-08 18:46 |只看该作者

论坛徽章:
0
8 [报告]
发表于 2011-12-09 10:05 |只看该作者
本帖最后由 yifei429 于 2011-12-09 10:08 编辑
kouu 发表于 2011-12-08 18:46

抢占是调度的时候调用的是preempt_schedule(),但如果刚好时间片到了呢?那应该调用的是schedule()吧?此时没有机会设置PREEMPT_ACTIVE?

论坛徽章:
0
9 [报告]
发表于 2011-12-09 10:46 |只看该作者
什么叫抢占?运行中的进程非自愿的让出CPU就是抢占。时间片到了,显然也是属于非自愿的。进程根本不知道时间片这回事,想着要继续运行呢,但是却被sched了。
所以时间片到,调用的也是preempt_schedule()。

时间片到的流程是这样的:
1、时钟中断触发,软中断里面会更新current的运行时间,并且判断是否应该抢占。如果要抢占,则设置TIF_NEED_RESCHED标记;
2、中断上下文结束的时候,看到TIF_NEED_RESCHED标记,会调用preempt_schedule_irq;
3、preempt_schedule_irq在schedule之前会设置PREEMPT_ACTIVE;

论坛徽章:
6
金牛座
日期:2013-10-08 10:19:10技术图书徽章
日期:2013-10-14 16:24:09CU十二周年纪念徽章
日期:2013-10-24 15:41:34狮子座
日期:2013-11-24 19:26:19未羊
日期:2014-01-23 15:50:002015年亚洲杯之阿联酋
日期:2015-05-09 14:36:15
10 [报告]
发表于 2011-12-09 10:51 |只看该作者
回复 1# yifei429
内核中经常有set_current_state(TASK_INTERRUPTIBLE);这段代码,并且还没有放入唤醒队列中(例如2.6.18中的do_poll函数),当执行完这段代码之后:
1.此时刚好时间片到期,那此进程是不是永远不会执行了?
2.此事发生抢占,会出现什么情况?

这个问题的确是可能发生的,但是内核通过一个标志PREEMPT_ACTIVE来防止这种情况的发生。
PREEMPT_ACTIVE的作用:防止已经处于非运行状态的进程还没有加入到相应的队列之前,就被抢占的情况发生。
具体代码在schedule函数中:
  1. asmlinkage void __sched schedule(void)
  2. {
  3.         struct task_struct *prev, *next;
  4.         long *switch_count;
  5.         struct rq *rq;
  6.         int cpu;

  7. need_resched:
  8.         preempt_disable();
  9.         cpu = smp_processor_id();
  10.         rq = cpu_rq(cpu);
  11.         rcu_qsctr_inc(cpu);
  12.         prev = rq->curr;
  13.         switch_count = &prev->nivcsw;

  14.         release_kernel_lock(prev);
  15. need_resched_nonpreemptible:

  16.         schedule_debug(prev);

  17.         /*
  18.          * Do the rq-clock update outside the rq lock:
  19.          */
  20.         local_irq_disable();
  21.         __update_rq_clock(rq);
  22.         spin_lock(&rq->lock);
  23.         clear_tsk_need_resched(prev);

  24.         if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
  25.                 if (unlikely((prev->state & TASK_INTERRUPTIBLE) &&
  26.                                 unlikely(signal_pending(prev)))) {
  27.                         prev->state = TASK_RUNNING;
  28.                 } else {
  29.                         deactivate_task(rq, prev, 1);
  30.                 }
  31.                 switch_count = &prev->nvcsw;
  32.         }

  33.         if (unlikely(!rq->nr_running))
  34.                 idle_balance(cpu, rq);

  35.         prev->sched_class->put_prev_task(rq, prev);
  36.         next = pick_next_task(rq, prev);

  37.         sched_info_switch(prev, next);

  38.         if (likely(prev != next)) {
  39.                 rq->nr_switches++;
  40.                 rq->curr = next;
  41.                 ++*switch_count;

  42.                 context_switch(rq, prev, next); /* unlocks the rq */
  43.         } else
  44.                 spin_unlock_irq(&rq->lock);

  45.         if (unlikely(reacquire_kernel_lock(current) < 0)) {
  46.                 cpu = smp_processor_id();
  47.                 rq = cpu_rq(cpu);
  48.                 goto need_resched_nonpreemptible;
  49.         }
  50.         preempt_enable_no_resched();
  51.         if (unlikely(test_thread_flag(TIF_NEED_RESCHED)))
  52.                 goto need_resched;
  53. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP