linux1号进程 2号进程,Linux0号进程,1号进程,2号进程

本文详细介绍了Linux系统启动时的0号进程(idle进程,也称swapper进程),如何启动1号进程(kernel_init)和2号进程(kthreadd)。0号进程在所有进程启动后变为idle进程,当无任务运行时执行。1号进程负责执行init可执行文件,而2号进程是所有内核线程的父进程。通过`ps`命令可以观察到1号进程是init,2号进程是kthreadd,它们的父进程是0号进程。
摘要由CSDN通过智能技术生成

本节我们将从linux启动的第一个进程说起,以及后面第一个进程是如何启动1号进程,然后启动2号进程。然后系统中所有的进程关系图做个简单的介绍

0号进程

0号进程,通常也被称为idle进程,或者也称为swapper进程。

0号进程是linux启动的第一个进程,它的task_struct的comm字段为"swapper",所以也成为swpper进程。

#define INIT_TASK_COMM "swapper"

当系统中所有的进程起来后,0号进程也就蜕化为idle进程,当一个core上没有任务可运行时就会去运行idle进程。一旦运行idle进程则此core就可以进入低功耗模式了,在ARM上就是WFI。

我们本节重点关注是0号进程是如何启动的。在linux内核中为0号进程专门定义了一个静态的task_struct的结构,称为init_task。

/*

* Set up the first task table, touch at your own risk!. Base=0,

* limit=0x1fffff (=2MB)

*/

struct task_struct init_task

= {

#ifdef CONFIG_THREAD_INFO_IN_TASK

.thread_info = INIT_THREAD_INFO(init_task),

.stack_refcount = ATOMIC_INIT(1),

#endif

.state = 0,

.stack = init_stack,

.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,

.tasks = LIST_HEAD_INIT(init_task.tasks),

.ptraced = LIST_HEAD_INIT(init_task.ptraced),

.ptrace_entry = LIST_HEAD_INIT(init_task.ptrace_entry),

.real_parent = &init_task,

.parent = &init_task,

.children = LIST_HEAD_INIT(init_task.children),

.sibling = LIST_HEAD_INIT(init_task.sibling),

.group_leader = &init_task,

RCU_POINTER_INITIALIZER(real_cred, &init_cred),

RCU_POINTER_INITIALIZER(cred, &init_cred),

.comm = INIT_TASK_COMM,

.thread = INIT_THREAD,

.fs = &init_fs,

.files = &init_files,

.signal = &init_signals,

.sighand = &init_sighand,

.blocked = { {0}},

.alloc_lock = __SPIN_LOCK_UNLOCKED(init_task.alloc_lock),

.journal_info = NULL,

INIT_CPU_TIMERS(init_task)

.pi_lock = __RAW_SPIN_LOCK_UNLOCKED(init_task.pi_lock),

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

.thread_pid = &init_struct_pid,

.thread_group = LIST_HEAD_INIT(init_task.thread_group),

.thread_node = LIST_HEAD_INIT(init_signals.thread_head),

};

EXPORT_SYMBOL(init_task);

这个结构体中的成员都是静态定义了,为了简单说明,对这个结构做了简单的删减。同时我们只关注这个结构中的以下几个字段,别的先不关注。

.thread_info    = INIT_THREAD_INFO(init_task),      这个结构在thread_info和内核栈的关系中有详细的描述

.stack        = init_stack,             init_stack就是内核栈的静态的定义

.comm        = INIT_TASK_COMM,  0号进程的名称。

在这么thread_info和stack都涉及到了Init_stack, 所以先看下init_stack在哪里设置的。

最终发现init_task是在链接脚本中定义的。

#define INIT_TASK_DATA(align) \

. = ALIGN(align); \

__start_init_task = .; \

init_thread_union = .; \

init_stack = .; \

KEEP(*(.data..init_task)) \

KEEP(*(.data..init_thread_info)) \

. = __start_init_task + THREAD_SIZE; \

__end_init_task = .;

在链接脚本中定义了一个INIT_TASK_DATA的宏。

其中__start_init_task就是0号进程的内核栈的基地址,当然了init_thread_union=init_task=__start_init_task的。

而0号进程的内核栈的结束地址等于__start_i

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值