linux init_task 的初始化
日期 |
内核版本 |
架构 |
作者 |
2017-03-17 |
Linux-3.4.0 |
arm |
jlovej |
Init_task 是系统的0号进程,又称swapper进程,又称idle任务。它是所有进程、线程的祖宗,包括1号进程init,2号内核线程kthreadd。
进入start_kernel,可以说就已经运行在init_task的上下文了,因为此时栈针sp已经指向init_task的栈了。
linux/arch/arm/kernel/init_task.c中:
structtask_struct init_task = INIT_TASK(init_task);
unionthread_union init_thread_union __init_task_data =
{ INIT_THREAD_INFO(init_task) };
init_thread_union即为init_task的栈,也是一个8K对齐的thread_info结构体。init_thread_union为静态变量,被编译到内核的data段。
linux/arch/arm/kernel/head.S中:
ENTRY(stext)
…
ldr r13, =__mmap_switched @address to jump to after
@mmu has been enabled
adr lr, BSYM(1f) @return (PIC) address
mov r8, r4 @set TTBR1 to swapper_pg_dir
ARM( add pc, r10, #PROCINFO_INITFUNC )
1: b __enable_mmu
系统使能mmu时,跳转到__turn_mmu_on,enablemmu后跳转到r13,即__mmap_switched,最后跳转到start_kernel。
linux/arch/arm/kernel/head-common.S中
__mmap_switched:
adr r3, __mmap_switched_data
ldmia r3!, {r4, r5, r6, r7}
cmp r4, r5 @Copy data segment if needed
1: cmpne r5, r6
ldrne fp, [r4], #4
strne fp, [r5], #4
bne 1b
mov fp, #0 @Clear BSS (and zero fp)
1: cmp r6,r7
strcc fp, [r6],#4
bcc 1b
ARM( ldmia r3, {r4, r5, r6, r7, sp})
str r9, [r4] @Save processor ID
str r1, [r5] @Save machine type
str r2, [r6] @Save atags pointer
bic r4, r0, #CR_A @Clear 'A' bit
stmia r7, {r0, r4} @Save control register values
b start_kernel
ENDPROC(__mmap_switched)
.align 2
.type __mmap_switched_data, %object
__mmap_switched_data:
.long __data_loc @r4
.long _sdata @r5
.long __bss_start @r6
.long _end @r7
.long processor_id @r4
.long __machine_arch_type @r5
.long __atags_pointer @r6
.long cr_alignment @r7
.long init_thread_union + THREAD_START_SP @ sp
.size __mmap_switched_data, . - __mmap_switched_data
其中,ARM( ldmia r3, {r4, r5, r6,r7, sp})赋值sp
sp = init_thread_union +THREAD_START_SP,即init_task的栈顶。
所以,之后start_kernel中的任务都是基于此sp。当然,中断有中断的栈。
http://blog.csdn.net/gatieme/article/details/51484562
一个普通进程,其userspace栈大小可以通过cat/proc/$pid/limits |grep stack 看到。栈大小是由task_struct->signal->rlim[RLIMIT_STACK]决定的,在该进程被创建时,rlim是复制从父进程的rlim:
do_fork àcopy_processà copy_signal:
memcpy(sig->rlim, current->signal->rlim, sizeofsig->rlim);
父进程又是复制爷爷的,爷爷又是复制祖宗的,最终还是拷贝的init_task的rlim。
而init_task的rlim在这定义的:
#define INIT_RLIMITS \
{ \
[RLIMIT_CPU] = { RLIM_INFINITY, RLIM_INFINITY }, \
[RLIMIT_FSIZE] = { RLIM_INFINITY, RLIM_INFINITY }, \
[RLIMIT_DATA] = { RLIM_INFINITY, RLIM_INFINITY }, \
[RLIMIT_STACK] = { _STK_LIM, _STK_LIM_MAX }, \
[RLIMIT_CORE] = { 0, RLIM_INFINITY }, \
[RLIMIT_RSS] = { RLIM_INFINITY, RLIM_INFINITY }, \
[RLIMIT_NPROC] = { 0, 0 }, \
[RLIMIT_NOFILE] = { INR_OPEN_CUR, INR_OPEN_MAX }, \
[RLIMIT_MEMLOCK] = { MLOCK_LIMIT, MLOCK_LIMIT }, \
[RLIMIT_AS] = { RLIM_INFINITY, RLIM_INFINITY }, \
[RLIMIT_LOCKS] = { RLIM_INFINITY, RLIM_INFINITY }, \
[RLIMIT_SIGPENDING] = { 0, 0 }, \
[RLIMIT_MSGQUEUE] = { MQ_BYTES_MAX, MQ_BYTES_MAX }, \
[RLIMIT_NICE] = { 0, 0 }, \
[RLIMIT_RTPRIO] = { 0, 0 }, \
[RLIMIT_RTTIME] = { RLIM_INFINITY, RLIM_INFINITY }, \
}
在我的系统上,#define_STK_LIM (8*1024*1024),用户态栈大小默认是8M。