• Linux内核架构读书笔记


    execve 启动新程序

    1. execve 实现

      系统相关     系统无关

      sys_execve  - >  do_execve

      do_execve 定义

    1 *
    2  * sys_execve() executes a new program.
    3  */
    4 int do_execve(char * filename,
    5     char __user *__user *argv,
    6     char __user *__user *envp,
    7     struct 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 {
     7     int mode;
     8     struct inode * inode = bprm->file->f_path.dentry->d_inode;
     9     int retval;
    10 
    11     mode = inode->i_mode;
    12     if (bprm->file->f_op == NULL)
    13         return -EACCES;
    14 
    15     bprm->e_uid = current->euid;
    16     bprm->e_gid = current->egid;
    17 
    18     if(!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
    19         /* Set-uid? */
    20         if (mode & S_ISUID) {
    21             current->personality &= ~PER_CLEAR_ON_SETID;
    22             bprm->e_uid = inode->i_uid;
    23         }
    24 
    25         /* 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          */
    31         if ((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     }
    36 
    37     /* fill in binprm security blob */
    38     retval = security_bprm_set(bprm);
    39     if (retval)
    40         return retval;
    41 
    42     memset(bprm->buf,0,BINPRM_BUF_SIZE);
    43     return 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;
     8     int (*load_binary)(struct linux_binprm *, struct  pt_regs * regs);
     9     int (*load_shlib)(struct file *);
    10     int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit);
    11     unsigned long min_coredump;    /* minimal dump size */
    12     int hasvdso;
    13 };

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

      load_binary加载普通程序

      load_shlib用于加载共享库。

      coredump error 下输出内存转储

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

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

      

  • 相关阅读:
    sql语句
    数据结构
    Collection接口
    【学习笔记】〖九度OJ〗题目1443:Tr A
    【学习笔记】〖九度OJ〗题目1104:整除问题
    【学习笔记】〖九度OJ〗题目1138:进制转换
    【学习笔记】〖九度OJ〗题目1326:Waiting in Line
    【学习笔记】〖九度OJ〗题目1437:To Fill or Not to Fill
    【学习笔记】〖九度OJ〗题目1153:括号匹配问题
    【学习笔记】〖九度OJ〗题目1161:Repeater
  • 原文地址:https://www.cnblogs.com/songbingyu/p/3683038.html
Copyright © 2020-2023  润新知