关于arm linux中kthread()中的do_exit()
来自本人的旧博客: http://blog.163.com/awaken_ing/blog/static/12061319720151129103139710
1. 问题
linux-3.10.86/kernel/kthread.c
static int kthread(void *_create)
{
...
/* we can't just return, we must preserve "self" on stack */
do_exit(ret);
}
这里注释说不能省略do_exit(), why?
2. 解
2.1 内核创建
内核创建的部分流程为: _switchto -> retfromfork -> kthread
linux-3.10.86/arch/arm/kernel/entry-common.S
/*
* This is how we return from a fork.
*/
ENTRY(ret_from_fork)
bl schedule_tail
cmp r5, #0
movne r0, r4
adrne lr, BSYM(1f)
movne pc, r5
1: get_thread_info tsk
b ret_slow_syscall
ENDPROC(ret_from_fork)
movne pc, r5 执行kthread()
2.2 如果没有do_exit
linux-3.10.86/kernel/exit.c
void do_exit(long code)
{
...
schedule();
BUG();
/* Avoid "noreturn function does return". */
for (;;)
cpu_relax(); /* For when BUG is null */
}
doexit()最后执行schedule(), 所以, 就不会调用到 retfromfork中的retslowsyscall. 看下retslow_syscall的汇编代码:
(gdb) disass ret_slow_syscall
Dump of assembler code for function ret_to_user:
...
0x8000e630 <+16>: ldr lr,[sp, #60]! ; 0x3c @get pc
...
0x8000e63c <+28>: ldmdb sp, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, sp, lr}^
0x8000e640 <+32>: nop ; (mov r0, r0)
0x8000e644 <+36>: add sp, sp, #12
0x8000e648 <+40>: movs pc, lr
End of assembler dump.
内核线程可能是在内核启动过程中创建的, 并不是由用户态触发而创建的, 故不应该执行ldr lr,[sp, #60]! , ldmdb sp, {... }^以及movs pc, lr. 所以, 需要调用doexit(). 这里也解释了内核线程的两种退出方式: call doexit() directly or return when 'kthreadshouldstop()' .
本文地址: https://awakening-fong.github.io/posts/other/arm_kthread_do_exit
转载请注明出处: https://awakening-fong.github.io
若无法评论, 请打开JavaScript, 并通过proxy.
blog comments powered by Disqus