init_task进程

1. 0号进程

进程的关键要素就是堆栈。处于什么进程,首先看SP指向哪个进程的堆栈。

2. 堆栈

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进程的管理与调度(五)

你可能感兴趣的:(进程)