linux可执行文件的加载和运行之一(1)
2009-06-10 14:00
274 查看
可执行文件的加载和运行 Execve系统调用可以调用一个可执行文件完全代替当前的进程,它在libc中的封装有几个API:
研究代码之前,我们先考虑一下进程的空间安排结构.在本站的<<uclibc中的malloc机制分析>>曾经描述过.我们再次把进程的空间结构图列出,如下如示:
int execl(const charp a t* h n a m e, const char a* rg 0, ... /* (char *) 0 */); int execv(const charp a t* h n a m e, char *consta rgv [] ); int execle(const charp a t* h n a m e, const char a* rg 0, ... /* (char *)0, char *cones nt v p [] */); int execve(const charp a t* h n a m e, char *consta rgv [], char *consten vp [] ); int execlp(const charf i l e* n a m e, const char a* rg 0, ... /* (char *) 0 */); int execvp(const charf i l e* n a m e, char *consta rgv [] );我们深入内核代码来研究一下可执行文件的加载过程.execve()系统调用的入口是sys_execve().代码如下:
asmlinkage int sys_execve(struct pt_regs regs) { int error; char * filename; //将用户空间的第一个参数(也就是可执行文件的路径)复制到内核 filename = getname((char __user *) regs.ebx); error = PTR_ERR(filename); if (IS_ERR(filename)) goto out; error = do_execve(filename, (char __user * __user *) regs.ecx, (char __user * __user *) regs.edx, ®s); if (error == 0) { task_lock(current); current->ptrace &= ~PT_DTRACE; task_unlock(current); /* Make sure we don't return using sysenter.. */ set_thread_flag(TIF_IRET); } //释放内存 putname(filename); out: return error; }系统调用的时候,把参数依次放在:ebx,ecx,edx,esi,edi,ebp寄存器.详情请参阅本站<< Linux中断处理之系统调用>>.第一个参数为可执行文件路径,第二个参数为参数的个数,第三个参数为可执行文件对应的参数.do_execve()是这个系统调用的核心,它的代码如下:
int do_execve(char * filename, char __user *__user *argv, char __user *__user *envp, struct pt_regs * regs) { //linux_binprm:保存可执行文件的一些参数 struct linux_binprm *bprm; struct file *file; unsigned long env_p; int retval; retval = -ENOMEM; bprm = kzalloc(sizeof(*bprm), GFP_KERNEL); if (!bprm) goto out_ret; //在内核中打开这个可执行文件 file = open_exec(filename); retval = PTR_ERR(file); //如果打开失败 if (IS_ERR(file)) goto out_kfree; sched_exec(); bprm->file = file; bprm->filename = filename; bprm->interp = filename; //bprm初始化,主要是初始化bprm->mm retval = bprm_mm_init(bprm); if (retval) goto out_file; //计算参数个数 bprm->argc = count(argv, MAX_ARG_STRINGS); if ((retval = bprm->argc) < 0) goto out_mm; //环境变量个数 bprm->envc = count(envp, MAX_ARG_STRINGS); if ((retval = bprm->envc) < 0) goto out_mm; retval = security_bprm_alloc(bprm); if (retval) goto out; //把要加载文件的前128 读入bprm->buf retval = prepare_binprm(bprm); if (retval < 0) goto out; //copy第一个参数filename retval = copy_strings_kernel(1, &bprm->filename, bprm); if (retval < 0) goto out; //bprm->exec:参数的起始地址(从上往下方向) bprm->exec = bprm->p; //copy环境变量 retval = copy_strings(bprm->envc, envp, bprm); if (retval < 0) goto out; //环境变量存放的起始地址 env_p = bprm->p; //copy可执行文件所带参数 retval = copy_strings(bprm->argc, argv, bprm); if (retval < 0) goto out; //环境变量的长度 bprm->argv_len = env_p - bprm->p; //到链表中寻找合适的加载模块 retval = search_binary_handler(bprm,regs); if (retval >= 0) { /* execve success */ free_arg_pages(bprm); security_bprm_free(bprm); acct_update_integrals(current); kfree(bprm); return retval; } out: free_arg_pages(bprm); if (bprm->security) security_bprm_free(bprm); out_mm: if (bprm->mm) mmput (bprm->mm); out_file: if (bprm->file) { allow_write_access(bprm->file); fput(bprm->file); } out_kfree: kfree(bprm); out_ret: return retval; }
研究代码之前,我们先考虑一下进程的空间安排结构.在本站的<<uclibc中的malloc机制分析>>曾经描述过.我们再次把进程的空间结构图列出,如下如示:
相关文章推荐
- linux可执行文件的加载和运行之二
- linux可执行文件的加载和运行之一(3)
- linux可执行文件的加载和运行之一(2)
- linux可执行文件的加载和运行之一(4)
- Linux 可执行文件 ELF结构 及程序加载运行
- linux可执行文件的加载和运行之一(5)
- linux可执行文件的加载和运行之一
- linux进程管理之可执行文件的加载和运行之二
- Linux 常用环境变量及作用和环境变量文件的详细介绍及其加载执行顺序
- linux可执行文件的加载过程
- Linux0.11内核--加载可执行二进制文件之1.copy_strings
- Linux0.11内核--加载可执行二进制文件之2.change_ldt
- Linux0.11内核--加载可执行二进制文件之3.exec
- linux0.11是如何加载并执行一个二进制可执行文件和shell脚本文件的?
- Linux中ELF格式 可执行文件+动态链接器 的加载
- 一个操作系统的实现(1):分析linux下如何运行一个执行文件
- linux下如何在终端上运行和安装可执行文件
- linux里运行可执行文件
- Linux 常用环境变量及作用和环境变量文件的详细介绍及其加载执行顺序
- java中的jar打包成可执行文件,可以避免在linux中的java程序运行时内存剧增现象