zoukankan      html  css  js  c++  java
  • Linux — 进程管理

    进程创建

    进程通过fork()创建的大致过程:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    
    extern int create_process(char* program, char** arg_list);
    
    int create_process(char* program, char** arg_list){
        pid_t child_pid;
        child_pid = fork();
        if(child_pid !=0 ){
            return child_pid;
        }else{
        execvp(program, arg_list);
        abort();
        }
    }
    

    概览图:

    编译知识

    静态库

    这里额外补充一些编译相关的内容。一个源码文件要变成可执行的程序,需要经过编译、链接。

    这里编译出的.o文件,就是ELF的第一种类型,可重定位文件,格式如下:

    • .text:存放编译好的二进制可执行代码

    • .data:已经初始化好的全局变量

    • .rodata:只读数据,例如字符创常量、const常量

    • .bss:未初始化全局变量,运行时会置0

    • .symtab:符号表,记录的是函数和变量

    • .strtab:字符串表、字符串常量和变量名

    在程序中我们提到过函数栈,局部变量是放在里的,在运行期随时分配、随时释放。这里讨论的是文件,还没到执行阶段。

    如要将函数作为库文件被重用,不能以.o的形式存在,而是要形成库文件,最简单的类型是静态链接库.a文件。

    ar cr libstaticprocess.a process.o
    # 形成二进制执行文件staticcreateprocess
    gcc -o staticcreateprocess createprocess.o -L. -lstaticprocess
    

    上述第二条命令链接时,createprocess.o调用了create_process函数,但不知道位置,通过将process.o合并进来,就可以确定位置了。这里形成了ELF的第二种格式:

    .o相似,文件被分为多个section,通过节头表来描述。这里除了段描述之外,最重要的是p_vaddr——加载到内存的虚拟地址。

    静态库特点:

    • 一旦链接,代码和变量的section都合并在一起。当程序运行后,就不依赖这个库是否存在

    • 但如果相同的代码段被多个程序使用时,在内存里就存在多份

    • 当静态库更新了,需重新编译二进制执行文件以应用更新

    动态库

    当动态链接库被链接到一个程序文件时,最后的程序文件并不包括动态链接库中的代码,而仅仅包括对动态链接库的引用,并且不保存动态链接库的全路径,仅保存其名称

    gcc -shared -fPIC -o libdynamicprocess.so process.o
    
    gcc -o dynamiccreateprocess createprocess.o -L. -ldynamicprocess
    

    执行此程序时,先寻找动态链接库,再进行加载。默认,系统在/lib/usr/lib 路径下寻找,找不到则报错。可以通过设定LD_LIBRARY_PATH环境变量,指定动态链接库的路劲。

    动态链接库,就是ELF的第三种类型,共享对象文件

    • 多个.interp的Segment,里面是ld-linux.so动态连接器,执行链接动作

    • 多个.plt.got.plt,分别是 过程链接表(PLT)全局偏移量表(GOT)

    接下来,我们来看下程序运行时,是如何将so文件动态链接到进程空间的?

    • dynamiccreateprocess程序调用libdynamicprocess.so里的create_process函数时,是运行时才去找的,编译压根不知道在哪,因此在PLT里建立一个PLT[x]——在二进制程序里,不直接调用函数,而是调用PLT[x]里的代理代码,它会在运行时找到真正的create_process函数

    • 去哪找?去GOT里——它会为create_process函数创建GOT[y],对应运行时 create_process函数在内存中真正的地址

    • GOT又是咋知道的?对于create_process函数,GOT在开始时会创建GOT[y],但开始这里没有真正的地址,因为不知道...,它又回调PLT,告诉他:你里面的代理代码来找我要create_process的真实地址,我不知道,你自己想想。

    • PLT只能去调用PLT[0],PLT[0]去调用GOT[2],这里面保存ld-linux.so入口函数,它去找到加载到内存中的libdynamicprocess.so里的create_process函数地址,然后把这个地址放到GOT[y]中,以供下次PLT[x]调用。

    运行程序为进程

    ELF二进制文件是如何加载到内存里的?

    static struct linux_binfmt elf_format = {
            .module         = THIS_MODULE,
            .load_binary    = load_elf_binary,
            .load_shlib     = load_elf_library,
            .core_dump      = elf_core_dump,
            .min_coredump   = ELF_EXEC_PAGESIZE,
    };
    

    具体调用链:do_execve->do_execveat_common->exec_binprm->search_binary_handler。

    在系统调用时,exec最终调用的是load_elf_binary.

    进程树

    所有进程的祖宗进程,就是系统启动时的init进程。init进程会启动很多daemon进程,为系统运行提供服务。然后启动getty,让用户登录,登录后运行shell。

    • 1号进程是/sbin/init,所有用户态进程的祖先

    • 2号进程是内核线程kthreadd,所有内核态的祖先

    • ps -ef下,用户态不带中括号,内核态带中括号

  • 相关阅读:
    PDF文件中的Form保存问题
    Understanding IP Fragmentation
    tcp ip guide IPsec IKE
    Windows安全事件日志中的事件编号与描述
    Cisco PIX fix up and Juniper firewall FTP ALG
    很好的IPSec介绍,详细解释了IKE协商的2个阶段的作用
    virtualbox 下运行Ubuntu 8.10的分辨率和guest additions的问题。
    Fixing the ‘Do you want to display nonsecure items’ message
    windows xp 开始菜单里面所有项目右键不起作用。
    HP backup and recovery manager
  • 原文地址:https://www.cnblogs.com/CocoML/p/14135367.html
Copyright © 2011-2022 走看看