Linux启动和0 1 2 号进程

在linux启动的C阶段start_kernel()的最后,rest_init()会开启两个进程:kernel_init,kthreadd,之后主线程变成idle线程。

 

idle进程:pid=0

前身是系统创建的一个进程,也是唯一一个没有通过fork()创建或者kernel_thread产生的进程。

idle进程的创建:vmlinux的入口是arch/arm/kernel/head.S,(关注ENTRY(stext)的位置)入口地址可以从kernel/arch/arm/kernel/vmlinux.lds.S得知文件,在该汇编文件中为pid为0的原始进程设置了执行环境,包括先禁止MMU,内核刚开始是用物理地址的,禁止I-Cache和D-Cache,然后读取RO,R1,R2,然后原是进程开始执行start_kernel()完成Linux内核的初始化工作。包括初始化页表,初始化中断向量表,初始化系统时间等。继而调用 fork(),创建第一个用户进程: 创建init进程(pid==1)的函数如下:
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

参考:https://www.cnblogs.com/zhiliao112/p/4051361.html

init进程:pid=1 (init进程由idle通过kernel_thread创建),第一个用户级进程

它会继续完成剩下的初始化工作,然后execve(/sbin/init), 成为系统中的其他所有进程的祖先,pid为0的idle进程在创建了init进程后,pid=0的进程调用 cpu_idle()演变成了idle进程。current_thread_info()->status |= TS_POLLING;init在演变成/sbin/init之前,会执行一部分初始化工作,其中一个就是 smp_prepare_cpus(),初始化SMP处理器,在这过程中会在处理每个从处理器时调用 task = copy_process(CLONE_VM, 0, idle_regs(&regs), 0, NULL, NULL, 0); init_idle(task, cpu);

特点:

(1)init进程是比较特殊,一个进程两个状态,init刚开始运行时是内核态,他属于内核线程,然后他自己运行了一个用户态下面的程序后,他自己强行转成了用户态,因为init进程自身完成了从内核态到用户态的过渡,因此后续的其他进程都可以工作在用户态下面的。

(2)init在内核态做了什么? 重点就是做了一件事情,就是挂载跟文件系统并试图找到用户态下的那个init程序。要运行这个应用程序就必须找到这个程序,要找到他就必须得挂载根文件系统,因为所有的应用程序都在文件系统中。

(3)init用户态做了什么?init大部分有意义的工作是在用户态下进行的,init进程对我们操作系统的意义在于其他所有的用户进程都直接或者间接派生来自init进程。说白了,init进程生了后面的所有进程。

(4)init进程如何从内核态跳转到用户态?还能回来不?
init进程在内核态下面时,通过一个函数kernel_execve来执行一个用户空间编译连接的应用程序,就跳跃到用户态了。需要注意的是:这个跳跃后进程号是不改变的,一直是进程1.
这个跳跃过程是单向的,一旦执行了init程序转到用户态下就回不来了。用户态下想进入内核态只有走API这一条路了。

init进程构建了用户交互界面
(1) init进程是其他用户进程的老祖,linux系统中一个进程的创建是通过其父进程创建出来的,根据这个理论只要有一个父进程就能生出来一堆子孙进程了。
(2) init启动了login进程、命令行进程、shell进程。
(3)shell进程启动了其他用户进程,命令行和shell一旦工作了,用户就可以在命令行通过 ./xx 的方式来执行其他应用程序。每个应用程序的运行就是一个进程。

0号进程->1号内核进程->1号用户进程(init进程)->getty进程->shell进程

  1. kernel_init函数在内核态运行,是内核代码

  2. init进程是内核启动并运行的第一个用户进程,运行在用户态下。

  3. 一号内核进程调用execve()从文件/etc/inittab中加载可执行程序init并执行,这个过程并没有使用调用do_fork(),因此两个进程都是1号进程。

 

守护进程:内核线程,是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理发生的事件。 

一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。

参考:https://blog.csdn.net/hunanchenxingyu/article/details/25084117

https://blog.csdn.net/u013165704/article/details/80519339

 

kthreadd进程:pid=2。一个特殊的守护进程。并始终运行在内核空间,负责所有内核进程的调度和管理

它的任务就是管理和调度其他内核线程kernel_thread, 会循环执行一个kthread的函数,该函数的作用就是运行kthread_create_list全局链表中维护的kthread, 当我们调用kernel_thread创建的内核线程会被加入到此链表中,因此所有的内核线程都是直接或者间接的以kthreadd为父进程 。

所有其它的内核线程的ppid 都是 2,也就是说它们都是由kthreadd thread创建的

https://blog.csdn.net/gatieme/article/details/51566690

 

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值