内核进程(二) —— 0号与1号进程初始化

本文详细介绍了Linux内核进程的初始化过程,从0号始祖进程的空函数执行,到1号进程的用户态初始化,包括内核栈的配置、0号进程的数据结构和1号进程的孤儿进程收养功能。内核栈大小通常为8K,0号进程主要执行初始化任务,而1号进程负责用户态的系统设置和孤儿进程管理。
摘要由CSDN通过智能技术生成

内核进程实现

本文章基于 Linux 2.6.11 编写

内核栈

每个进程的执行流都需要一个栈空间来保存代码执行时所有上下文,包括变量地址和上层函数地址等,在内核态,这个栈就是内核栈。Linux的进程切换还需要使用汇编手动的将一些寄存器值存放在内核栈中,内核栈由以下结构体定义给出。

#define THREAD_SIZE		(8192)
union thread_union {
   
	struct thread_info thread_info;
	unsigned long stack[THREAD_SIZE/sizeof(long)];
};

struct thread_info {
   
	struct task_struct	*task;		/* 进程描述符地址*/
	unsigned long		flags;		/**< 存放 TIF_XXX
                                     * 最重要的就是 TIF_NEED_RESCHED
                                     */
	unsigned long		status;		/* thread-synchronous flags */
    __u32			    cpu;		/**< 所在的运行CPU current CPU */
	__s32			    preempt_count; /**< 调度计数器,等于0,方可调度 */
    ...
};

大多情况下,我们都将内核栈配置成 8K 大小,所以在进行内核开发时,函数中不要使用过大的栈变量。为了快速的传递和访问当前进程内核态的一些重要数据,我们将这些数据称为线程信息 struct thread_info,并存放在内核栈的起始处,如下图。

__va(x) 用于计算物理页号对应的虚地址


    __va(pfn+2)  +-----------+<--- ebp 栈基地址
                 |   stack   |
                 |    ||     |
                 |    ||     |     栈向低地址增长
                 |    ||     |
      8096       |    \/     |
                 +-----------+<--- esp 当前栈顶
                 |   unused  |
                 +-----------+
                 |thread_info|
    __va(pfn)    +-----------+<--- current 指向处

当使用 esp 的值进行简单的位运算,屏蔽掉低 13 位的有效位就可以得到每个进程的 thread_info 结构的地址,其中存放了 包括 struct task 进程描述地址 在内的重要信息,这样做我们就不必在每个需要使用这些信息的内核函数参数中携带 thread_info 地址指针。由于 struct task 也包含 thread_info 指针,所以整个算法是直接返回当前进程的 task 进程描述符,并使用 current 表示。

static inline struct thread_info *current_thread_info(void)
{
   
	struct thread_info *ti;
	__asm__("andl %%esp,%0; ":"=r" (ti) : "0" (~(THREAD_SIZE - 1)));
	return ti;
}
static inline struct task_struct * get_current(void)
{
   
	return current_thread_info()->task;
}
#define current get_current()

0号始祖进程

当一个CPU启动后,第一个执行流在经过一系列初始化后就形成0号进程,0号进程不做任何实际的工作,只是运行一个空函数,该函数除了检查是否已被抢占,就仅仅死循环执行空指令或挂起CPU等待中断,直到系统停止。可以配置多种不同的空函数,下面给出默认空函数。

void cpu_idle(void)
{
   
    ...
	while (1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值