当前位置:首页 > 操作系统 > Linux

Linux内核架构读书笔记 - 2.4.3 启动新线程

execve 启动新程序

  1. execve 实现

  系统相关     系统无关

  sys_execve  - >  do_execve

  do_execve 定义

            1 *
2  * sys_execve() executes a new program.
3  */
4int do_execve(char * filename,
5char __user *__user *argv,
6char __user *__user *envp,
7struct pt_regs * regs)

  do_execve 执行流程图

    首先打开内核文件,具体可见第八章

    bprm_init

      mm_alloc 生成新的mm_struct 实例管理进程地址空间

      init_new_context 特定于体系,用于初始化该实例

      __bprm_mm_init 建立初始的栈

    新进程的各个参数会合并到一个struct linux_binprm *bprm;的机构。 prepare_binprm用于提供一些父进程相关的值

    prepare_binprm也维护了SUID SGID位的处理

             1
            /*
             2
             * Fill the binprm structure from the inode. 

             3
             * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes

             4
            */
             5
            int prepare_binprm(struct linux_binprm *bprm)
 6{
 7int mode;
 8struct inode * inode = bprm->file->f_path.dentry->d_inode;
 9int retval;
1011     mode = inode->i_mode;
12if (bprm->file->f_op == NULL)
13return -EACCES;
1415     bprm->e_uid = current->euid;
16     bprm->e_gid = current->egid;
1718if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
19/* Set-uid? */20if (mode & S_ISUID) {
21             current->personality &= ~PER_CLEAR_ON_SETID;
22             bprm->e_uid = inode->i_uid;
23        }
2425/* Set-gid? */26/*27         * If setgid is set but no group execute bit then this
28         * is a candidate for mandatory locking, not a setgid
29         * executable.
30*/31if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
32             current->personality &= ~PER_CLEAR_ON_SETID;
33             bprm->e_gid = inode->i_gid;
34        }
35    }
3637/* fill in binprm security blob */38     retval = security_bprm_set(bprm);
39if (retval)
40return retval;
4142     memset(bprm->buf,0,BINPRM_BUF_SIZE);
43return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);
44 }

    search_binary_handler用于在do_execve 结束是查找一种适当的二进制格式,具体细节(待补充。。。)

    二进制格式处理程序负责将新的程序数据加载到旧的地址空间中,

    二进制格式处理程序执行步骤如下:

  1.  释放原进程资源
  2.  将应用进程映射到虚拟地址空间
    1. text 段,start_code 和 end_code 指定该段在地址空间驻留区域
    2. 预先初始化的数据位于start_data和end_data之间
    3. heap 用于动态内存分配,亦置于虚拟地址空间中,start_brk和brk 指定其边界
    4. stack 由start_stack 定义,几乎所有体系自动向下增长,PA-Risc是例外,对于栈的反向增长,体系结构的相关部分必须告诉内核,可以通过设置符号STACK_DROWSUP 
    5. 程序的参数与环境也映射到虚拟地址空间中,分别位于arg_start 和arg_end 之间
  3.  设置进程的相关指令和其他特定于体系结构的寄存器,以便调度器选择该进程时候开始执行程序的main函数

  2 解释二进制格式

             1
            /*
             2
             * This structure defines the functions that are used to load the binary formats that

             3
             * linux accepts.

             4
            */
             5
            struct
             linux_binfmt {

             6
            struct
             list_head lh;

             7
            struct module *module;
 8int (*load_binary)(struct linux_binprm *, struct  pt_regs * regs);
 9int (*load_shlib)(struct file *);
10int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
11     unsigned long min_coredump;    /* minimal dump size */12int hasvdso;
13 };

  每种二进制格式提供下面三个函数

  load_binary加载普通程序

  load_shlib用于加载共享库。

  coredump error 下输出内存转储

 

  每种二进制格式需要使用register_binfmt向内核注册。该函数的目的是向一个链表增加一个新的二进制格式

  该链表表头是fs/exec.c的全局变量formats, linux_binfmt 实例通过其next成员彼此联系起来

 

原文:http://www.cnblogs.com/songbingyu/p/3683038.html


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐