161---linux实验二

来源:互联网 发布:淘宝手机店招图片素材 编辑:程序博客网 时间:2024/06/06 03:40

【实验要求】分析forkexec系统调用在内核中的执行过程。

注意:task_struct进程控制块,ELF文件格式与进程地址空间的联系,注意Exec系统调用返回到用户态时EIP指向的位置;动态链接库在ELF文件格式中与进程地址空间中的表现形式。


实验总结:   

    当一个进程被创建时,系统会为该进程分配进程空间,并且每个进程都有一个进程描述符task_struct,该数据结构中包含了与该进程相关的所有信息,比如众多描述进程属性的字段,以及指向其他与进程相关的结构体的指针。其中有指向mm_struct结构体的指针mm,这个结构体是对该进程用户空间的描述。

    每个ELF可执行文件中不仅包含代码段,还包括数据段、bss以及程序的入口点等,由于可执行文件结构本身的设计,使得它很容易被加载,这使得连续的可执行文件组块可以被映射到连续的存储器段,代码段中的段头表描述了这种映射关系。

    当前进程调用fork时产生子进程,子进程的用户级虚拟地址空间是父进程虚拟地址空间的一份拷贝,包括文本、数据段、bss段、堆以及用户栈,同时子进程获得了与父进程任何打开文件描述符相通的拷贝,这意味着子进程可以读写父进程打开的任何文件。而子进程与父进程最大的区别就是他们有不同的PID

    当子进程调用execl(const char *path, const char *arg,NULL)时,启动加载器,加载器删除子进程已有的虚拟存储器段,按照path路径所指向的可执行文件段头表的指导,将可执行文件的相关内容加载到了当前子进程的上下文中(代码段和数据段等),它会覆盖当前子进程的地址空间,并继承了调用execl函数时打开的所有文件描述符,并且新的程序仍然具有相同的PID,这样就产生了一个全新的子进程,最后加载器跳转到新进程_start地址,它最终会调用应用的main函数并运行。

实验内容:

    代码如图所示:

    经编译后执行,所得结果如图所示:


    结果分析:

    原进程调用fork,fork是c库提供的API,对应同名系统调用函数,系统调用fork在内核中对应的服务例程为sys_fork,它又调用了函数do_fork,里面调用的函数copy_process()就是对进程进行拷贝的关键函数。此时,存在主进程1与子进程0,进程0是进程1的完全的拷贝,只是它们拥有不同的PID。

    此时父进程1执行wait,处于休眠状态,所以进程0先执行。子进程调用execl函数对可执行文件ls进行加载,函数读取ELF文件的头部,根据ELF文件的头部信息扫描程序段描述表,将可执行文件代码数据等其映射到进程的地址空间。最后通过修改eip寄存器的值将返回的入口地址设置成应用程序的入口,使其指向加载的应用程序的入口。

    此时子进程已变成全新的子进程,并运行新进程。当新进程运行结束后,父进程1再执行。

实验分析:

1)进程控制块task_struct:

    task_struct,就是进程描述符(process descriptor),该数据结构中包含了与一个进程相关的所有信息,比如包含众多描述进程属性的字段,以及指向其他与进程相关的结构体的指针。其中有指向mm_struct结构体的指针mm,这个结构体是对该进程用户空间的描述;也有指向fs_struct结构体的指针fs,这个结构体是对进程当前所在目录的描述;也有指向files_struct结构体的指针files,这个结构体是对该进程已打开的所有文件进行描述;另外还有一个小型的进程描述符thread_info,结构如下图所示。


2)ELF文件格式与进程地址空间的联系:

    当子进程调用exec时,启动加载器,加载器删除子进程已有的虚拟存储器段,按照path路径所指向的可执行文件段头表的指导,将ELF可执行文件的相关内容加载到了当前子进程的上下文中(代码段和数据段等),它会覆盖当前子进程的地址空间,从而实现文件组块与进程空间地址的映射。


3)动态链接库在ELF文件格式中与进程地址空间中的表现形式:

    应用程序通常都需要使用动态链接库,当在 shell 中敲入一个命令要执行时,内核会创建一个新的进程,它在往这个新进程的进程空间里面加载进可执行程序的代码段和数据段后,也会加载进动态连接器(在Linux里面通常就是 /lib/ld-linux.so 符号链接所指向的那个程序,它本省就是一个动态库)的代码段和数据。在这之后,内核将控制传递给动态链接库里面的代码。动态连接器接下来负责加载该命令应用程序所需要使用的各种动态库。加载完毕,动态连接器才将控制传递给应用程序的main函数。如此,应用程序才得以运行。

    为了让动态连接器能成功的完成动态链接过程,在前面运行的连接编辑器需要在应用程序可执行文件中生成数个特殊的 sections,比方 .dynamic、.dynsym、.got和.plt等等。

    ELF文件里面,每一个 sections 内都装载了性质属性都一样的内容,比方:

(1) .text section 里装载了可执行代码;

(2) .data section 里面装载了被初始化的数据;

(3) .bss section 里面装载了未被初始化的数据;

(4) 以 .rec 打头的 sections 里面装载了重定位条目;

(5) .symtab 或者 .dynsym section 里面装载了符号信息;

(6) .strtab 或者 .dynstr section 里面装载了字符串信息;

(7) 其他还有为满足不同目的所设置的section,比方满足调试的目的、满足动态链接与加载的目的等等。

   动态链接库在ELF文件格式中与进程地址空间中的表现形式,如下如所示:



原创粉丝点击