初始化0号进程

arch/x86/kernel/head_32.S的336行,进入分页后的内核代码段,执行lss stack_start,%esp指令,立即为进程0建立内核态堆栈。stack_start定义在657行:

657 ENTRY(stack_start)

658        .long init_thread_union+THREAD_SIZE

659        .long __BOOT_DS

 

我们看到内核态堆栈由init_thread_union表示,其在include/linux/sched.h中被定义成一个全局变量:

extern union thread_union init_thread_union;

union thread_union {

       struct thread_info thread_info;

       unsigned long stack[THREAD_SIZE/sizeof(long)];

};

 

#define THREAD_SIZE        (PAGE_SIZE << THREAD_ORDER)

 

由于PAGE_SIZE是4096,THREAD_ORDER在32位x86体系中是1,所以THREAD_SIZE的值为8k。所以这个thread_union的大小也为8k。关于内核栈的详细内容请参考博客“进程相关的数据结构” .

 

那么,对于一个进程,最重要的是什么呢?两个东西,一个是thread_info,另一个就是著名的task_struct。这个0号进程的thread_info,我们已经看到了,是在init_thread_union中。那么这个task_struct又在哪儿呢?看到arch/x86/kernel/init_task.c:

23 union thread_union init_thread_union __init_task_data =

  24        { INIT_THREAD_INFO(init_task) };

 

扎眼一看,很奇怪,怎么多了个__init_task_data?别紧张,其实,它只是一个宏,不是什么变了,来自include/linux/init_task.h的186行:

#define __init_task_data __attribute__((__section__(".data.init_task")))

 

那么,上面的内容就展开成了:

union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) =

{ INIT_THREAD_INFO(init_task) };

 

这是一条赋值语句,对联合体init_thread_union赋初始值。晕了吧,c语言的功底是多么重要啊,通过内核的学习,你也学会了如何对联合体赋初值并且把数据放进指定的数据段.data.init_task了吧。

 

继续,具体到如何赋值呢?先讲讲init_task这个全局变量,定义在arch/x86/kernel/init_task.c的第31行:

struct task_struct init_task = INIT_TASK(init_task);

 

这不,0号进程的task_struct出现了,就是init_task。在对init_thread_union赋初值的时候,同时也通过调用INIT_TASK宏对init_task赋初值:

 

110#define INIT_TASK(tsk)  /

 111{                                                                       /

 112        .state          = 0,                                            /

 113        .stack          = &init_thread_info,                            /

 114        .usage          = ATOMIC_INIT(2),                               /

 115        .flags          = PF_KTHREAD,                                   /

 116        .lock_depth     = -1,                                           /

 117        .prio           = MAX_PRIO-20,                                  /

 118        .static_prio    = MAX_PRIO-20,                                  /

 119        .normal_prio    = MAX_PRIO-20,                                  /

 120        .policy         = SCHED_NORMAL,                                 /

 121        .cpus_allowed   = CPU_MASK_ALL,                                 /

 122        .mm             = NULL,                                         /

 123        .active_mm      = &init_mm,                                     /

 124        .se             = {                                             /

 125                .group_node     = LIST_HEAD_INIT(tsk.se.group_node),    /

 126        },                                                              /

 127        .rt             = {                                             /

 128                .run_list       = LIST_HEAD_INIT(tsk.rt.run_list),      /

 129                .time_slice     = HZ,                                   /

 130                .nr_cpus_allowed = NR_CPUS,                             /

 131        },                                                              /

 132        .tasks          = LIST_HEAD_INIT(tsk.tasks),                    /

 133        .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), /

 134        .ptraced        = LIST_HEAD_INIT(tsk.ptraced),                  /

 135        .ptrace_entry   = LIST_HEAD_INIT(tsk.ptrace_entry),             /

 136        .real_parent    = &tsk,                                         /

 137        .parent         = &tsk,                                         /

 138        .children       = LIST_HEAD_INIT(tsk.children),                 /

 139        .sibling        = LIST_HEAD_INIT(tsk.sibling),                  /

 140        .group_leader   = &tsk,                                         /

 141        .real_cred      = &init_cred,                                   /

 142        .cred           = &init_cred,                                   /

 143        .cred_guard_mutex =                                             /

 144                 __MUTEX_INITIALIZER(tsk.cred_guard_mutex),             /

 145        .comm           = "swapper",                                    /

 146        .thread         = INIT_THREAD,                                  /

 147        .fs             = &init_fs,                                     /

 148        .files          = &init_files,                                  /

 149        .signal         = &init_signals,                                /

 150        .sighand        = &init_sighand,                                /

 151        .nsproxy        = &init_nsproxy,                                /

 152        .pending        = {                                             /

 153                .list = LIST_HEAD_INIT(tsk.pending.list),               /

 154                .signal = {{0}}},                                       /

 155        .blocked        = {{0}},                                        /

 156        .alloc_lock     = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),         /

 157        .journal_info   = NULL,                                         /

 158        .cpu_timers     = INIT_CPU_TIMERS(tsk.cpu_timers),              /

 159        .fs_excl        = ATOMIC_INIT(0),                               /

 160        .pi_lock        = __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),        /

 161        .timer_slack_ns = 50000, /* 50 usec default slack */            /

 162        .pids = {                                                       /

 163                [PIDTYPE_PID]  = INIT_PID_LINK(PIDTYPE_PID),            /

 164                [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID),           /

 165                [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),            /

 166        },                                                              /

 167        .dirties = INIT_PROP_LOCAL_SINGLE(dirties),                     /

 168        INIT_IDS                                                        /

 169        INIT_PERF_EVENTS(tsk)                                           /

 170        INIT_TRACE_IRQFLAGS                                          /

 171        INIT_LOCKDEP                                                 /

 172        INIT_FTRACE_GRAPH                                          /

 173        INIT_TRACE_RECURSION                                       /

 174        INIT_TASK_RCU_PREEMPT(tsk)                                 /

 175}

 

至于task_struct的详细介绍,请查看博客“进程相关的数据结构”,这里只挑几个重要的来说说。0号进程的stack就是刚才init_thread_info的地址;parent是他自己;thread是INIT_THREAD。还有一些是常量,如init_fs。等我们用到了再回过来看它。

 

现在,0号进程task_struct有了,下面就该来讲讲INIT_THREAD_INFO宏了,在arch/x86/include/asm/thread_info.h:

 

  46#define INIT_THREAD_INFO(tsk)                   /

  47{                                               /

  48        .task           = &tsk,                 /

  49        .exec_domain    = &default_exec_domain, /

  50        .flags          = 0,                    /

  51        .cpu            = 0,                    /

  52        .preempt_count  = INIT_PREEMPT_COUNT,   /

  53        .addr_limit     = KERNEL_DS,            /

  54        .restart_block = {                      /

  55                .fn = do_no_restart_syscall,    /

  56        },                                      /

  57}

 

执行完这个宏以后,init_thread_union就被初始化成以上内容了,至此,0号进程的task_struct和thread_info就初始化完毕了。注意,这个初始化不是在head_32.S中初始化的。大家也看到了,上面的内容都是在编译的时候作为一个数据全局数据被初始化的,并且把他们放在.data.init_task数据段中。head_32.S中只是将esp指针指向这个已经被初始化了的init_thread_union以上8k作为栈顶,并向下移动(回忆一下c程序的特点,并参考“进程相关的数据结构”中那个图)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值