进程的创建与可执行程序的加载

本文详细介绍了如何使用fork函数创建子进程以及如何利用exec函数族在子进程中加载并执行新的可执行程序。此外还深入探讨了ELF文件格式及其与进程地址空间之间的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程的创建与可执行程序的加载

张颜(SA*****111) 


fork函数


fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,子进程返回0,父进程返回子进程ID,出错返回-1;子进程是父进程的副本,子进程从父进程那得到了数据空间,堆和栈,但不是与父进程共享而是单独分配内存,即父进程与子进程有独立的地址空间。父子进程共享正文段。fork函数返回后,子进程和父进程都是从fork函数的下一条语句开始执行。

使用例程:



运行效果:



fork系统调用


fork这个API函数由C库提供,在C库中封装了与其同名的系统调用fork(),该系统调用对编程者是隐藏的,编程者只需知道如何使用这些API即可。系统调用在内核中并不是直接实现的,而是通过调用各自对应的服务例程。系统调用fork在内核中对应的服务例程为sys_fork()。该服务例程定义在linux/arch/i386/kernel/process.c中,可以看到sys_fork()调用了do_fork(),而后者又调用了copy_process()。

对fork调用反汇编,观察其在内核中的执行过程:





exec函数


用fork函数创建子进程后,子进程往往要调用一种exec函数一执行另一个程序。当进程调用一种exec函数时,该进程执行的程序完全被替换为新程序,而新程序则从其main函数开始执行。因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用一个全新的程序替换了当前进程的正文、数据、堆和栈。

使用例程:




exec系统调用


所有exec函数(除execve()外)都是C库定义的封装例程 ,并利用了execve()系统调用,这是Linux所提供的处理程序执行的唯一系统调用。系统调用execve()在内核中对应的服务例程为sys_execve()。sys_execve()把可执行文件路径名拷贝到一个新分配的页框。然后调用do_execve()函数,传递给它的参数为指向这个页框的指针、指针数组的指针及把用户态寄存器内容保存到内核态堆栈的位置。

对execl调用反汇编,观察其在内核中的执行过程:




利用fork与exec实现在子进程中加载可执行程序


使用例程:

forkandexec.c



test.c(对应可执行文件test):



运行./forkandexec:


在上图中们可以发现,子进程并没有打印"execl error",这是因为子进程执行的程序已完全被execl替换为新程序。


进程描述符的结构




ELF文件介绍


ELF文件主要有三种类型: 

1、可重定位文件:包含了代码和数据.可与其它ELF文件建立一个可执行或共享的文件 
2、可执行文件:是可以直接执行的程序
3、共享目标文件:包括代码和数据,可以在两个地方链接。第一,连接器可以把它和其它可重定位文件和共享文件一起处理以建立另一个ELF文件;第二,动态链接器把它和一个可执行文件和其它共享文件结合在一起建立一个进程映像


ELF文件参与程序的连接(建立一个程序)和程序的执行(运行一个程序),编译器和链接器将其视为节头表(section header table)描述的一些节(section)的集合,而加载器则将其视为程序头表(program header table)描述的段(segment)的集合,通常一个段可以包含多个节。可重定位文件都包含一个节头表,可执行文件都包含一个程序头表。共享文件两者都包含有。为此,ELF文件格式同时提供了两种看待文件内容的方式,反映了不同行为的不同要求。如下图所示:


  

从链接的角度看,ELF文件从开始到结束,可以看成是如下组成的: 
a)ELF文件头 
b)程序头表(可选) 
c)第1节,第2节,...,第n节,... 
d)节头表 

从执行的角度看,ELF文件从开始到结束,可以看成是如下组成的: 
a)ELF文件头 
b)程序头表 
c)第1段,第2段,...
d)节头表(可选)

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


ELF文件格式中的 ELF头部、程序头部表、.init、.text、.rodata段对应进程地址空间中的代码段。 ELF文件格式中的 .data、.bss段对应进程地址空间中的数据段。

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

动态链接库在ELF文件中对应着.dynamic段所包含的信息,在进程地址空间对应其共享库区域段。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值