Linux内核之进程和系统调用

一.fork和execl

  我们先尝试编写创建两个程序,来理解Linux创建新进程的过程:

 1 #include <sys/systypes.h>
 2 #include <unistd.h>
 3 
 4 int main()
 5 {
 6     if (fork() == 0) {
 7         print("Child process!\n");
 8     } else {
 9         print("Parent process!\n");
10     }
11     return 0;
12 }

  运行结果为:

Child process!
Parent process!

  代码二

 1 #include <sys/types.h>
 2 #include <unistd.h>
 3 #include <stdio.h>
 4 
 5 int main()
 6 {
 7     execl("./hello_world", NULL, NULL);
 8     printf("execl failed!");
 9     return 0;
10 }

  运行结果

Hello World!

  通过上面的对比,可以看错:fork实际上是复制了一个“自己”,在fork之后有两个自己在运行。子进程和父进程是依靠fork的返回值是否为0来决定执行流。返回值为0则是子进程。返回值不是0则是父进程。

  execl则是将执行的内容完全替换掉。在execl之后,执行的完全是一个新的进程。就进程不复存在。

  可以将fork看作是复制,而execl则是替换。

  linux就是这样创建进程的:fork一个进程,在用execl加载新的执行程序,替换新建的进程的执行内容。比如ls:bash通过fork一个新的bash,再execl("ls")来创建一个ls进程。

二.系统调用的过程

  想要详细定位fork和execl在内核中的实现需要了解linux系统调用的处理流程。我们以fork为例子。我们可以通过下面的代码调用fork:

#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int  main()
{
    pid_t pid;

    // pid = fork();
    asm volatile(
        "mov $0x2, %%eax\n\t" // 将fork的系统调用号2存到eax寄存器  
        "int $0x80\n\t"       // 产生int 0x80中断
        "mov %%eax,%0\n\t"    // 将结果存入pid中
        : "=m" (pid) 
    );
    
    if (pid == 0) {
        printf("Child process\n");
    } else if (pid > 0) {
        printf("Parent process\n");
    }

    return 0;
}

  这样就能通过内核调用fork了。可以看到我们是通过int 0x80这条指令实现的。实际上,这是一个中断。我们通过128号中断调用内核的中断服务例程,调用fork的。

  在系统调用的过程中,我们需要记住两张表。

  一、中断向量表:在内核启动时初始化,然后当有中断发生时,内核就会根据中断向量号(如:0x80),查找对应的中断处理服务程序。

  二、系统调用表:在编译内核时就已经卸载内核中,系统调用处理程序会根据系统调用号处理对应的系统调用程序。

  

  例如,上图的getpid函数,然后进入getuid系统调用。getuid进入system_call系统中断服务例程,system_call再去调用sys_getuid16运行服务例程。

三. 查找对应的内核服务例程

  通过上面的理解,我们就可以很快的使用source insight来查找fork和execl对应的内核服务例程了。

  fork对应的是:kernel/fork.c中的sys_fork函数

  execl对应的是:fs/exec.c中的sys_execl函数。

  这些函数太过复杂,需要非常好的基础才能看懂。我目前基础不够,只能结合《深入理解linux内核》中的进程和文件系统两章做一点简单的理解。这里就无法再做分析了。只对理解的部分做出一点总结。

原文地址:https://www.cnblogs.com/SA226343/p/3134543.html