结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程

结合中断上下文切换和进程上下文切换分析Linux内核一般执行过程

  • 以fork和execve系统调用为例分析中断上下文的切换
  • 分析execve系统调用中断上下文的特殊之处
  • 分析fork子进程启动执行时进程上下文的特殊之处
  • 以系统调用作为特殊的中断,结合中断上下文切换和进程上下文切换分析Linux系统的一般执行过程

 

一、fork系统调用

  fork系统调用用于创建一个新进程,称为子进程,它与进程(称为系统调用fork的进程)同时运行,此进程称为父进程。创建新的子进程后,两个进程将执行fork()系统调用之后的下一条指令。子进程使用相同的pc(程序计数器),相同的CPU寄存器,在父进程中使用的相同打开文件。
 
  它不需要参数并返回一个整数值。下面是fork()返回的不同值。
    负值:创建子进程失败。
    零:返回到新创建的子进程。
    正值:返回父进程或调电者。该值包含新创建的子进程的进程ID
 
  fork是?个系统调?,和?般的系统调?执?过程?致是?样的。

  首先用户程序调用fork()发出一个软中断,由entry_SYSCALL_64 ()进入系统调用入口,保存用户态现场,进入内核态,再由do_syscall_64根据系统调用号来执行相应的系统调用函数,进而调用_do_fork()函数完成相应功能。

  _do_fork函数主要完成了调?copy_process()创建子进程,再调?wake_up_new_task将?进程加?就绪队列等待调度执?等。

  之后恢复用户态现场,返回用户态,继续向下执行。

  ?进程复制了?进程中所有的进程上下文信息,包括内核堆栈、进程描述符等,?进程作为?个独?的进程也会被调度。复制?进程的资源时采?了Copy OnWrite(写时复制)技术,不需要修改的进程资源??进程是共享内存存储空间的。

二、execve系统调用

  execve系统调用的作用是运行另外一个指定的程序。它会把新程序加载到当前进程的内存空间内,当前的进程会被丢弃,它的堆、栈和所有的段数据都会被新进程相应的部分代替,然后会从新程序的初始化代码和 main 函数开始运行。同时,进程的 ID 将保持不变。

  execve系统调用通常与 fork系统调用配合使用。从一个进程中启动另一个程序时,通常是先 fork一个子进程,然后在子进程中使用 execve变身为运行指定程序的进程。 例如,当用户在 Shell 下输入一条命令启动指定程序时,Shell 就是先 fork了自身进程,然后在子进程中使用 execve来运行指定的程序。

  execve系统调用的过程大概如下:

      1.陷入内核;

      2.加载新的可执行文件并进行可执行性检查;

      3.将新的可执行文件映射到当前运行进程的进程空间中,并覆盖原来的进程数据;

      4.将EIP的值设置为新的可执行程序的入口地址。

      5.返回用户态,程序从新的EIP出开始继续往下执行。至此,老进程的上下文已经被新的进程完全替代了,但是进程的PID还是原来的。

  execve系统调用中断上下文的特殊之处在于,新的运行进程中已经找不到原来的对execve调用的代码了,所以execve函数不会成功返回,而是实现了一次完全的变身。

三、Linux系统的一般执行过程

• (1)正在运?的?户态进程X。

• (2)发?中断(包括异常、系统调?等),CPU完成load cs:rip(entry of a speci?c ISR),即跳转到中断处理程序??。

• (3)中断上下?切换,具体包括如下?点:

• • swapgs指令保存现场,可以理解CPU通过swapgs指令给当前CPU寄存器状态做了?个快照。

• • rsp point to kernel stack,加载当前进程内核堆栈栈顶地址到RSP寄存器。快速系统调?是由系统调???处的汇编代码实现?户堆栈和内核堆栈的切换。

• • save cs:rip/ss:rsp/r?ags:将当前CPU关键上下?压?进程X的内核堆栈,快速系统调?是由系统调???处的汇编代码实现的。

• 此时完成了中断上下?切换,即从进程X的?户态到进程X的内核态。

• (4)中断处理过程中或中断返回前调?了schedule函数,其中完成了进程调度算法选择next进程、进程地址空间切换、以及switch_to关键的进程上下?切换等。

• (5)switch_to调?了__switch_to_asm汇编代码做了关键的进程上下?切换。将当前进程X的内核堆栈切换到进程调度算法选出来的next进程(本例假定为进程Y)的内核堆 栈,并完成了进程上下?所需的指令指针寄存器状态切换。之后开始运?进程Y(这?进程Y曾经通过以上步骤被切换出去,因此可以从switch_to下??代码继续执?)。

• (6)中断上下?恢复,与(3)中断上下?切换相对应。注意这?是进程Y的中断处理过程中,?(3)中断上下?切换是在进程X的中断处理过程中,因为内核堆栈从进程X 切换到进程Y了。

• (7)为了对应起?中断上下?恢复的最后?步单独拿出来(6的最后?步即是7)iret - pop cs:rip/ss:rsp/r?ags,从Y进程的内核堆栈中弹出(3)中对应的压栈内容。此时完 成了中断上下?的切换,即从进程Y的内核态返回到进程Y的?户态。注意快速系统调?返回sysret与iret的处理略有不同。

• (8)继续运??户态进程Y

结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程

上一篇:linux文件管理类命令及实例讲解


下一篇:shell 强化1