本文分析linux内核exec系统调用执行过程中可执行文件的加载过程和栈的设置,内核代码版本为2.6.32

分析

\arch\ia64\kernel\process.c中有sys_exec函数的实现,是exec的系统调用服务例程

long
sys_execve (char __user *filename, char __user * __user *argv, char __user * __user *envp,
        struct pt_regs *regs)
{
    char *fname;
    int error;
  //得到文件名字
    fname = getname(filename);
    error = PTR_ERR(fname);
    if (IS_ERR(fname))
        goto out;
    error = do_execve(fname, argv, envp, regs);
    putname(fname);
out:
    return error;
}

\fs\namei.c中有getname函数的实现,在getname中,会从slab分配器中分配空间,然后从用户空间读取名字。所以sys_execve的主要工作有do_execve来实现,do_execve实现在\fs\exec.c中,下面分析do_execve的实现

首先是共享打开文件描述符

 struct files_struct *displaced;
retval = unshare_files(&displaced);

unshare是linux中名称空间的控制函数,files_struct是挂靠在进程文件描述符上的,表示一个进程打开文件的信息,包含打开文件列表等待信息。这里的unshare_files就是复制原打开文件列表,所以说,exec后,子进程是共享父进程的打开文件列表的,包括标准输入输出和错误输出

struct linux_binprm *bprm;
bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);

这里动态分配了linux_binprm结构,linux_binprm是exec过程中信息的结构

/*
 * This structure is used to hold the arguments that are used when loading binaries.
 */
struct linux_binprm{
    char buf[BINPRM_BUF_SIZE];
#ifdef CONFIG_MMU
    struct vm_area_struct *vma;
#else
# define MAX_ARG_PAGES    32
    struct page *page[MAX_ARG_PAGES];
#endif
    struct mm_struct *mm;
    unsigned long p; /* current top of mem */
    unsigned int
        cred_prepared:1,/* true if creds already prepared (multiple
                 * preps happen for interpreters) */
        cap_effective:1;/* true if has elevated effective capabilities,
                 * false if not; except for init which inherits
                 * its parent's caps anyway */
#ifdef __alpha__
    unsigned int taso:1;
#endif
    unsigned int recursion_depth;
    struct file * file;
    struct cred *cred;    /* new credentials */
    int unsafe;        /* how unsafe this exec is (mask of LSM_UNSAFE_*) */
    unsigned int per_clear;    /* bits to clear in current->personality */
    int argc, envc;
    char * filename;    /* Name of binary as seen by procps */
    char * interp;        /* Name of the binary really executed. Most
                   of the time same as filename, but could be
                   different for binfmt_{misc,script} */
    unsigned interp_flags;
    unsigned interp_data;
    unsigned long loader, exec;
};
linux_binprm结构

相关文章: