美文网首页
内核中进程0里不能使用堆栈的原因

内核中进程0里不能使用堆栈的原因

作者: sgy1993 | 来源:发表于2017-09-07 13:36 被阅读0次

也即 : 关于pause和fork的内嵌问题
首先,我们要明确的是,不是任务0从main开始执行就不能使用栈,它可以使用栈,比如它按函数方式调用了
trap_init等,这些都会"污染"栈,但是这些栈都在函数返回时被自动清理了.
我们说的任务0不能使用栈,是指在执行fork之前,要保证栈中没有多余的内容.
而由于普通C的调用函数都会用到栈,所以fork才使用汇编的方式被调用 .
但根本原因是:
任务0和任务1都使用同一个栈,此时我们已经不用管它是属于内核还是用户。

总之任务0使用一个栈区,而任务1(一开始也"被迫"使用这个栈区)。

在任务0在用户栈调用 fork时,如果以普通函数调用的方式,那么此时用户栈中肯定会被以下内容"污染"


Fork后原下一条指令的地址


任务0的栈顶ebp ?----- 新的esp栈


然后中断到系统调用 fork中去。

而forkà copy_process 中

将把旧任务(即任务0)的所有寄存器内容(包括栈相关的SS:ESP)都复制给任务1

而虽然现在没有真正在主内存中给任务1分配物理内存空间,但这会在将来能过Copy-on-write的方式来复制到主内存,创建任务1的栈

接着fork调用完了后,返回。但是由于fork本身也是一个系统调用 ,只要是系统调用返回时都会进行schedule检查。

所以内核并不能保证fork返回后,任务0和任务1哪个先执行。

如果任务1先执行,并且它进行了栈操作。则产生page fault,进行copy-on-write,然后任务1的真正的用户栈被建立 ,但是建立是以先复制任务0的栈为前提的

而此时任务0的栈中有上面提到的"污染"内容在里面。

如果任务0先执行,那么在fork返回后,虽然任务0将它的栈"清空",但是紧接着任务0会执行pause调用 ,如果还是以函数的方式,则在任务0调用pause返回前,如果不巧,进行了schedule到任务1,任务1又使用了栈的话,又会造成上面的情况。

相关文章

  • Linux内核——用户堆栈和内核堆栈

    定义 每个进程都有用户堆栈和内核堆栈两个堆栈。进程在用户态时使用用户堆栈,陷入到内核态时便使用内核堆栈。 切换过程...

  • 内核中进程0里不能使用堆栈的原因

    也即 : 关于pause和fork的内嵌问题首先,我们要明确的是,不是任务0从main开始执行就不能使用栈,它可以...

  • 进程内核栈、用户栈

    1.1. 进程的堆栈 内核在创建进程的时候,在创建task_struct的同时,会为进程创建相应的堆栈。每个进程会...

  • 用户栈与内核栈有什么区别

    内核在创建进程时,会同时创建task_struct和进程相应堆栈。每个进程都会有两个堆栈,一个用户栈,存在于用户空...

  • Binder(一)Linux进程通信

    用户空间、内核空间 Linux分为内核进程和用户进程:1、内核进程共享一块内存空间,称为内核空间。2、内核进程不能...

  • 死锁问题排查

    首先使用jps查询进程ID然后使用jstack和进程ID查询堆栈日志信息。

  • linux内核进程控制

    进程 进程由可执行的指令代码、数据和堆栈区组成,在linux中,除了第一个进程是“手工”建立以外,其余都是进程使用...

  • 带您进入内核开发的大门 | 内核中的线程

    内核线程是直接由内核本身启动的进程。内核线程实际上是将内核函数委托给独立的进程,它与内核中的其他进程”并行”执行。...

  • RHEL7 运行级别简介及切换操作

    init是Linux系统操作中不可缺少的程序之一。init进程,它是一个由内核启动的用户级进程。内核会在过去曾使用...

  • 多进程(fork)

    Fork: 产生:使用fork函数得到的子进程从父进程的继承了整个进程的地址空间,包括:进程上下文、进程堆栈、内存...

网友评论

      本文标题:内核中进程0里不能使用堆栈的原因

      本文链接:https://www.haomeiwen.com/subject/hwlijxtx.html