为什么新进程设置成TASK_RUNNING可防止被信号唤醒?

30 views
Skip to first unread message

Gao Feng

unread,
Aug 29, 2016, 7:00:20 PM8/29/16
to 《linux环境编程》讨论组, Li Bin
第5.4.3节,sched_fork有这样一行代码p->state = TASK_RUNNING;描述是这样“此举的目的是防止外部信号和时间将其唤醒,之后插入运行队列。”。


我的问题是,为什么设置成TASK_RUNNING,就可以防止呢?

华贵斌

unread,
Aug 30, 2016, 5:26:44 AM8/30/16
to 《linux环境编程》讨论组, beanli...@gmail.com
系统wakeup进程的时候会判断进程state,只会唤醒符合TASK_ALL即(TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE | __TASK_STOPPED | __TASK_TRACED)的进程。所以我理解的是把进程状态设置成TASK_RUNNING后,系统认为该进程不需要唤醒,所以不会再去唤醒它。

在 2016年8月30日星期二 UTC+8上午7:00:20,Gao Feng写道:

Feng Gao

unread,
Aug 30, 2016, 5:54:49 AM8/30/16
to 华贵斌, 《linux环境编程》讨论组, Li Bin
贴一下内核代码吧。
> --
> 您收到此邮件是因为您订阅了Google网上论坛上的“《linux环境编程》讨论组”群组。
> 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到linux_aple+...@googlegroups.com
> 要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/linux_aple/49294054-2d6e-478f-aee5-adf9ab7aa756%40googlegroups.com
> 要查看更多选项,请访问https://groups.google.com/d/optout

华贵斌

unread,
Aug 30, 2016, 6:51:26 AM8/30/16
to 《linux环境编程》讨论组, huag...@gmail.com, beanli...@gmail.com
kernel version 2.6.32-431

sched.h:205-207:
这里是对TASK_ALL宏的定义,注释也说明了该宏也是用于wake_up的
/* Convenience macros for the sake of wake_up */
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
#define TASK_ALL (TASK_NORMAL | __TASK_STOPPED | __TASK_TRACED)

sched.c:
2680-2695:
对于新建task,由于尚未加入任何等待队列,所以不会被__wake_up()系列函数唤醒,好像也只可能被wake_up_process()唤醒
/**
 * wake_up_process - Wake up a specific process
 * @p: The process to be woken up.
 *
 * Attempt to wake up the nominated process and move it to the set of runnable
 * processes.  Returns 1 if the process was woken up, 0 if it was already
 * running.
 *
 * It may be assumed that this function implies a write memory barrier before
 * changing the task state if and only if any tasks are woken up.
 */
int wake_up_process(struct task_struct *p)
{
return try_to_wake_up(p, TASK_ALL, 0);
}
EXPORT_SYMBOL(wake_up_process);

2549-2678:
/***
 * try_to_wake_up - wake up a thread
 * @p: the to-be-woken-up thread
 * @state: the mask of task states that can be woken
 * @sync: do a synchronous wakeup?
 *
 * Put it on the run-queue if it's not already there. The "current"
 * thread is always on the run-queue (except when the actual
 * re-schedule is in progress), and as such you're allowed to do
 * the simpler "current->state = TASK_RUNNING" to mark yourself
 * runnable without the overhead of this.
 *
 * returns failure only if the task is already active.
 */
static int try_to_wake_up(struct task_struct *p, unsigned int state,
 int wake_flags)
{
int cpu, orig_cpu, this_cpu, success = 0;
unsigned long flags;
unsigned long en_flags = ENQUEUE_WAKEUP;
struct rq *rq;

this_cpu = get_cpu();

smp_wmb();
rq = task_rq_lock(p, &flags);
/*此处对task的state进行判断*/
if (!(p->state & state))
goto out;
......

核心思想就是在对task结构初始化完成前,不要让task进入running queue,所以把可能导致task进入running queue的路径堵死。
欢迎指正:)


在 2016年8月30日星期二 UTC+8下午5:54:49,Gao Feng写道:
贴一下内核代码吧。

2016-08-30 17:26 GMT+08:00 华贵斌 <huag...@gmail.com>:
> 系统wakeup进程的时候会判断进程state,只会唤醒符合TASK_ALL即(TASK_INTERRUPTIBLE |
> TASK_UNINTERRUPTIBLE | __TASK_STOPPED |
> __TASK_TRACED)的进程。所以我理解的是把进程状态设置成TASK_RUNNING后,系统认为该进程不需要唤醒,所以不会再去唤醒它。
>
> 在 2016年8月30日星期二 UTC+8上午7:00:20,Gao Feng写道:
>>
>> 第5.4.3节,sched_fork有这样一行代码p->state =
>> TASK_RUNNING;描述是这样“此举的目的是防止外部信号和时间将其唤醒,之后插入运行队列。”。
>>
>>
>> 我的问题是,为什么设置成TASK_RUNNING,就可以防止呢?
>>
> --
> 您收到此邮件是因为您订阅了Google网上论坛上的“《linux环境编程》讨论组”群组。
> 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到linux_aple+unsubscribe@googlegroups.com

Feng Gao

unread,
Aug 30, 2016, 7:03:07 AM8/30/16
to 华贵斌, 《linux环境编程》讨论组, Li Bin
果然如毛主席所说“群众的眼光是雪亮的~~~”

但我还有一个疑问。这时这个进程刚刚创建,有谁又能够wakeup它呢?
也就是说在什么情况下,新创建的进程,还没有初始化完毕,别人通过什么途径可以wakeup它呢?
>> > 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到linux_aple+...@googlegroups.com
>> >
>> > 要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/linux_aple/49294054-2d6e-478f-aee5-adf9ab7aa756%40googlegroups.com
>> > 要查看更多选项,请访问https://groups.google.com/d/optout
>
> --
> 您收到此邮件是因为您订阅了Google网上论坛上的“《linux环境编程》讨论组”群组。
> 要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到linux_aple+...@googlegroups.com
> 要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/linux_aple/65e21bbc-d12e-42c8-be98-cf5f1beb7561%40googlegroups.com
> 要查看更多选项,请访问https://groups.google.com/d/optout
Message has been deleted

Feng Gao

unread,
Sep 1, 2016, 12:20:10 AM9/1/16
to 华贵斌, 《linux环境编程》讨论组, Li Bin
是个可能性,赞同。

2016-08-31 11:13 GMT+08:00 华贵斌 <huag...@gmail.com>:
> 这里我也有点疑惑,我理解的是,从 task设置为TASK_RUNNING开始 到
> 事实上将task放入cpu的运行队列(do_fork()中调用wake_up_new_task())
> 这段时间内,新进程有可能会被信号唤醒进入运行队列,比如kill(-1, signo)等情况。
>
>
> 在 2016年8月30日星期二 UTC+8下午7:03:07,Gao Feng写道:
> 要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/linux_aple/35123936-1f6e-493e-94eb-6a84c9626a55%40googlegroups.com
> 要查看更多选项,请访问https://groups.google.com/d/optout
Reply all
Reply to author
Forward
0 new messages