欢迎来到皮皮网网首页

【python看源码提高】【暗黑传奇手机源码】【java大型网站 源码】linux execve 源码

来源:源码签到 时间:2024-11-25 09:27:59

1.linux内核情景分析之execve的实现
2.通过do_execve源码分析程序的执行(上)(基于linux0.11)
3.如何使用linux commands step by step
4.Linux 可执行文件程序载入和执行过程

linux execve 源码

linux内核情景分析之execve的实现

       Linux内核中的execve函数实现涉及到用户态CPU寄存器在内核栈中的保存和系统调用的细节。首先,理解sys_execve源码中的do_execve函数至关重要。它涉及到一个名为linux_bin_fmt的结构,该结构存储了内核对各种可执行程序格式的支持信息,包括加载和执行函数,python看源码提高以及保存文件路径、参数和环境变量的linux_bin_prm结构。

       do_execve的实现从读取可执行文件的头部字节开始,通过prepare_binprm函数,将文件头部数据放入bprm->buf缓存。内核通过search_binary_handler遍历formats队列,识别文件的正确格式并调用相应的处理函数,如load_aout_binary处理a.out格式。

       在load_aout_binary中,暗黑传奇手机源码如遇到/bin/echo,会调用flush_old_exec,涉及信号处理函数指针复制、内存空间处理(包括信号处理模式、用户空间的清理)和文件关闭等。其中,make_private_signal和exec_mmap函数分别处理信号处理和内存映射,根据close_on_exec位图关闭相关文件。

       在载入新程序时,内核会复制可执行文件路径到内核空间,然后查找并打开文件,读取前字节初始化数据结构。接下来,通过formats队列的java大型网站 源码遍历,找到合适的代理加载器(如a.out的load_aout_binary)来执行后续的加载和初始化操作,如设置信号处理、用户空间和文件资源等。

       最终,新进程会通过各个代理加载器的定制化空间申请和参数映射,调用start_thread启动进程。尽管描述了大致流程,但实际执行中涉及许多细节问题,如线程隔离、用户空间计数处理等,需要深入内核代码才能详细了解。

通过do_execve源码分析程序的执行(上)(基于linux0.)

       execve函数是操作系统的关键功能,它允许程序转变为进程。本文通过剖析do_execve源码,完美西游源码揭示程序转变成进程的机制。do_execve被视为系统调用,其运行过程在前文已有详细解析,此处不再赘述。分析将从sys_execve函数开启。

       在执行_do_execve前,先审视内核栈。接下来,我们将深入理解do_execve的实现。

       在加载可执行文件时,存在两种情况:编译后的二进制文件与脚本文件。脚本文件需加载对应解释器,本文仅探讨编译后的二进制文件。解析流程如下:首先验证文件可执行性和当前进程权限,源码上传哪个文件通过后,仅加载头部数据,具体代码在真正运行时通过缺页中断加载。然后,申请物理内存并存储环境变量和参数,该步骤在copy_string函数中实现。

       完成上述步骤后,内核栈结构发生变化。接着,执行代码释放原进程页目录和页表项信息,解除物理地址映射,这些信息通过fork继承。随后,调用change_ldt函数设置代码段、数据段基地址和限长,其中数据段限长为MB,代码段限长根据执行文件头部信息确定。完成物理地址映射后,内存布局随之调整。

       紧接着,通过create_tables函数分配执行环境变量和参数的数组。执行完毕后,内存布局进一步调整。最后,设置栈、堆位置,以及eip为执行文件头部指定值,esp为当前栈位置,至此,可执行文件加载阶段完成。下文将探讨执行第一条指令后的后续步骤。

如何使用linux commands step by step

       æ•™ç§‘书里的Linux代码例子都已作古,所以看到的代码不能当真,领会意思就行了

       æ¯”如以前的init进程的启动代码

       execve(init_filename,argv_init,envp_init);

       çŽ°åœ¨æ”¹ä¸º

       static void run_init_process(char *init_filename)

       {

       argv_init[0] = init_filename;

       kernel_execve(init_filename, argv_init, envp_init);

       }

       å¥½çš„,聪明人就发现,linux内核中调用用户空间的程序可以使用init这样的方式,调用 kernel_execve

       ä¸è¿‡å†…核还是提供了更好的辅助接口call_usermodehelper,自然最后也是调用kernel_execve

       è°ƒç”¨ç‰¹å®šçš„内核函数(系统调用)是 GNU/Linux 中软件开发的原本就有的组成部分。但如果方向反过来呢,内核空间调用用户空间?确实有一些有这种特性的应用程序需要每天使用。例如,当内核找到一个设备,这时需要加载某个模块,进程如何处理?动态模块加载在内核通过 usermode-helper 进程进行。

       è®©æˆ‘们从探索 usermode-helper 应用程序编程接口(API)以及在内核中使用的例子开始。 然后,使用 API 构造一个示例应用程序,以便更好地理解其工作原理与局限。

       usermode-helper API

       usermode-helper API 是个很简单的 API,其选项为用户熟知。例如,要创建一个用户空间进程,通常只要设置名称为 executable,选项都为 executable,以及一组环境变量(指向 execve 主页)。创建内核进程也是一样。但由于创建内核空间进程,还需要设置一些额外选项。

Linux 可执行文件程序载入和执行过程

       在 Linux 系统中,可执行文件的加载和执行过程涉及到 ELF(Executable and Linking Format)格式。当你在终端输入命令执行一个可执行程序时,bash 程序首先通过 fork() 创建一个新的进程,然后新进程通过 execve() 系统调用来启动指定程序。

       execve() 函数原型如下:它接收程序文件名、参数和环境变量作为输入。进入内核后,调用 sys_execve(),接着是 do_execve(),这里会根据 ELF 文件构建一个 linux_binprm 内核结构,存储文件信息,并根据文件类型决定执行方式。load_elf_binary 是关键接口,它主要负责初始化这个结构并处理加载过程。

       结构中,`linux_binprm` 包含了文件路径、参数数组、文件属性等信息,其中参数是按栈方式存放的。在 load_elf_binary 中,首先验证 ELF 文件的标识,确认其类型和机器架构,接着读取程序头部信息,包括动态链接器路径。如果文件需要动态链接,会加载并处理解释器(动态链接器)。

       然后,它会清除父进程相关代码,设置内存映射,如环境变量、堆栈地址等,并将执行入口设置为 ELF 文件的 e_entry。最后,调用 start_thread() 函数将 CPU 的 EIP(指令指针)和 ESP(堆栈指针)设置为新的地址,使得系统从内核态返回时,CPU会直接进入新程序的入口地址,完成程序的装载和执行。

       阅读更多关于 Linux 系统调用、进程间通信、资源限制、性能诊断、系统工具等内容,可以在相关文章中找到详细说明。如果你对 Linux 进一步感兴趣,可以关注相关技术公众号获取更多深入内容。