进程的关键要素就是堆栈。处于什么进程,首先看SP指向哪个进程的堆栈。
2.1 堆栈的初始化
进程init_task的定义在init/init_task.c中
/* Initial task structure */
struct task_struct init_task = INIT_TASK(init_task);
EXPORT_SYMBOL(init_task);
INIT_TASK的宏定义在include/linux/init_task.h中
#define INIT_TASK(tsk) \
{ \
.state = 0, \
.stack = &init_thread_info, \
.usage = ATOMIC_INIT(2), \
.flags = PF_KTHREAD, \
.prio = MAX_PRIO-20, \
.static_prio = MAX_PRIO-20, \
.normal_prio = MAX_PRIO-20, \
.policy = SCHED_NORMAL, \
.cpus_allowed = CPU_MASK_ALL, \
.nr_cpus_allowed= NR_CPUS, \
.mm = NULL, \
.active_mm = &init_mm, \
.restart_block = { \
.......
}
可以看出init_task进程的堆栈是指向init_thread_info。
在文件arch/arm/include/asm/thread_info.h中,init_thread_info的定义如下。
#define init_thread_info (init_thread_union.thread_info)
可以看出init_thread_info是init_thread_union的成员thread_info。
变量 init_thread_info的定义在init/init_task.c中:
union thread_union init_thread_union __init_task_data =
{ INIT_THREAD_INFO(init_task) };
#define INIT_THREAD_INFO(tsk) \
{ \
.task = &tsk, \
.flags = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
}
#define __init_task_data __attribute__((__section__(".data..init_task")))
说明:
1)声明了thread_union类型的init_thread_union变量,然后给init_thread_union中的thread_info thread_info成员赋值,主要是init_thread_union.thread_info thread_info.task=&init_task,将这个变量的task成员指向init_task。
2) attribute((section(".data…init_task"))),指定section名字是.data…init_task,将会被编译进去vmlinux的.data的开始处。
2.2 堆栈编译进vmlinux
243 .data : AT(__data_loc) {
244 _data = .; /* address in memory */
245 _sdata = .;
246
247 /*
248 * first, the init task union, aligned
249 * to an 8192 byte boundary.
250 */
251 INIT_TASK_DATA(THREAD_SIZE)
======>
. = ALIGN(8192); \
*(.data..init_task)
.data…init_task(init_thread_union )的section编译进vmlinux。
可以用objdump从vmlinux读出init_thread_union的地址或者System.map中读出.
可以看出init_thread_union被加载到0x80678000,大小为0x2000。
2.3 设置SP指针
在执行start_kernel之前,把SP指针设置为init_thread_union+8K-8的地方,然后执行start_kernel,这样在
96 ARM( ldmia r3, {r4, r5, r6, r7, sp})
97 THUMB( ldmia r3, {r4, r5, r6, r7} )
98 THUMB( ldr sp, [r3, #16] )
99 str r9, [r4] @ Save processor ID
100 str r1, [r5] @ Save machine type
101 str r2, [r6] @ Save atags pointer
102 cmp r7, #0
103 strne r0, [r7] @ Save control register values
104 b start_kernel
105 ENDPROC(__mmap_switched)
106
107 .align 2
108 .type __mmap_switched_data, %object
109 __mmap_switched_data:
110 .long __data_loc @ r4
111 .long _sdata @ r5
112 .long __bss_start @ r6
113 .long _end @ r7
114 .long processor_id @ r4
115 .long __machine_arch_type @ r5
116 .long __atags_pointer @ r6
117 #ifdef CONFIG_CPU_CP15
118 .long cr_alignment @ r7
119 #else
120 .long 0 @ r7
121 #endif
122 .long init_thread_union + THREAD_START_SP @ sp
123 .size __mmap_switched_data, . - __mmap_switched_data
linux init_task 的初始化
Linux进程的管理与调度(五)