我试图了解
linux内核中的init进程,这是第一个进程,并使用INIT_TASK宏进行静态初始化.
161 #define INIT_TASK(tsk) \ 162 { \ 163 .state = 0,\ 164 .stack = &init_thread_info,\ 165 .usage = ATOMIC_INIT(2),\ 166 .flags = PF_KTHREAD,\ 167 .prio = MAX_PRIO-20,\ 168 .static_prio = MAX_PRIO-20,\ 169 .normal_prio = MAX_PRIO-20,\ 170 .policy = SCHED_NORMAL,\ 171 .cpus_allowed = cpu_MASK_ALL,\ 172 .nr_cpus_allowed= NR_cpuS,\ 173 .mm = NULL,\ 174 .active_mm = &init_mm,\ 175 .se = { \ 176 .group_node = LIST_HEAD_INIT(tsk.se.group_node),\ 177 },\ 178 .rt = { \ 179 .run_list = LIST_HEAD_INIT(tsk.rt.run_list),\ 180 .time_slice = RR_TIMESLICE,\ 181 },\ 182 .tasks = LIST_HEAD_INIT(tsk.tasks),\ 183 INIT_PUSHABLE_TASKS(tsk) \ 184 INIT_CGROUP_SCHED(tsk) \ 185 .ptraced = LIST_HEAD_INIT(tsk.ptraced),\ 186 .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry),\ 187 .real_parent = &tsk,\ 188 .parent = &tsk,\ 189 .children = LIST_HEAD_INIT(tsk.children),\ 190 .sibling = LIST_HEAD_INIT(tsk.sibling),\ 191 .group_leader = &tsk,\ 192 RCU_POINTER_INITIALIZER(real_cred,&init_cred),\ 193 RCU_POINTER_INITIALIZER(cred,\ 194 .comm = INIT_TASK_COMM,\ 195 .thread = INIT_THREAD,\ 196 .fs = &init_fs,\ 197 .files = &init_files,\ 198 .signal = &init_signals,\ 199 .sighand = &init_sighand,\ 200 .nsproxy = &init_nsproxy,\ 201 .pending = { \ 202 .list = LIST_HEAD_INIT(tsk.pending.list),\ 203 .signal = {{0}}},\ 204 .blocked = {{0}},\ 205 .alloc_lock = __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),\ 206 .journal_info = NULL,\ 207 .cpu_timers = INIT_cpu_TIMERS(tsk.cpu_timers),\ 208 .pi_lock = __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),\ 209 .timer_slack_ns = 50000,/* 50 usec default slack */ \ 210 .pids = { \ 211 [PIDTYPE_PID] = INIT_PID_LINK(PIDTYPE_PID),\ 212 [PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID),\ 213 [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID),\ 214 },\ 215 .thread_group = LIST_HEAD_INIT(tsk.thread_group),\ 216 INIT_IDS \ 217 INIT_PERF_EVENTS(tsk) \ 218 INIT_TRACE_IRQFLAGS \ 219 INIT_LOCKDEP \ 220 INIT_FTRACE_GRAPH \ 221 INIT_TRACE_RECURSION \ 222 INIT_TASK_RCU_PREEMPT(tsk) \ 223 INIT_cpuSET_SEQ \ 224 INIT_VTIME(tsk) \ 225 }
但我无法弄明白
>它将如何执行?
>预定的地点和
>当我们说我们已经安排了这个init_task任务时,linux内核中的哪些代码行会立即开始执行?它有什么功能吗?
解决方法
内核调用“init”作为内核初始化过程中最后的事情之一. init / main.c中的函数
kernel_init()
具有逻辑.
您会注意到内核尝试了四种不同的init组合,并期望其中一种成功.您还会注意到,您可以通过提供内核命令行参数“init”来覆盖内核在启动时执行的操作.因此,您可以在内核命令行中说出init = / bin / mystartup,并启动您自己的自定义应用程序而不是默认的/ sbin / init.另请注意,在大多数现代系统中,即使是嵌入式系统,/ sbin / init也是指向真实可执行文件的软链接.
为了更一般地回答你的问题,研究这个源文件(main.c)你可以看到几乎所有Linux内核初始化的细节,在低级程序集和平台初始化之后,这超出了教育价值,你不应该’不得不接触或关心.
主要机制是用fixed arguments of argv_init
and envp_init
调用do_execve()
.解析elf文件并根据文件设置初始程序计数器(PC).所有内存管理(mm)页面都映射到磁盘后备存储.代码设置为运行.在计划的初始PC提取时,会生成页面错误,将第一个代码页读入内存.这与任何其他execve()调用相同.