在Linux下面,对二进制程序有着严格的格式要求,这就是ELF,这个格式可以根据编译的结果不同,分为不同的格式。

ELF的三种类型

一:可重定位文件

在编译的时候,先做预处理工作,例如将头文件嵌入到正文中,将定义的宏展开,然后就是真正 的编译过程,最终编译成为.o文件,这就是ELF的第一种类型,可重定位文件,长这样:

二、可执行文件:

要想让函数作为库文件被重用,不能以.o的形式存在,而是要形成库文件,最简单的类型是静态链接库.a文件(Archives),仅仅将一系列对象文件(.o)归档为一个文 件,使用命令ar创建

ar cr libstaticprocess.a process.o

虽然这里libstaticprocess.a里面只有一个.o,但是实际情况可以有多个.o。当有程序要使用这个静态连接库的时候,会将.o文件提取出来,链接到程序中。在这个命令里,-L表示在当前目录下找.a文件,-lstaticprocess会自动补全文件名,比如加前缀 lib,后缀.a,变成libstaticprocess.a,找到这个.a文件后,将里面的process.o取出来,和 createprocess.o做一个链接,形成二进制执行文件staticcreateprocess。这个链接的过程,重定位就起作用了,原来createprocess.o里面调用了create_process函数,但是不能确定位置,现在将process.o合并了进来,就知道位置了,形成的二进制文件叫可执行文件,是ELF的第二种格式

这个格式和.o文件大致相似,还是分成一个个的section,并且被节头表描述。只不过这些section是多个.o文件合并过的。但是这个时候,这个文件已经是马上就可以加载到内存里面执行的文件了,因而这些section被分成了需要加载到内存里面的代码段、数据段和不需要加载到内存里面的部分,将小的section合成了大的段segment,并且在最前面加一个段头表 (Segment Header Table)。在代码里面的定义为struct elf32_phdr和struct elf64_phdr,这里面除了有对于段的描述之外,最重要的是p_vaddr,这个是这个段加载到内存的虚拟地址。

三、共享对象文件

静态链接库有个缺点,就是一旦链接进去,代码和变量的section都合并了,因而程序运行的时候,就不依赖于这个库是否存在,是相同的代码段,如果被多个程序使用的话,在内存里面就有多份,而且一旦静态链接库更新了,如果二进制执行文件不重新编译,也不随着更新。因为出现了另外一种——动态链接库,不仅是一组对象文件的简单归档,而是多个对象文件的重新组合,可被多个程序共享。

gcc -shared -fPIC -o libdynamicprocess.so process.o

当一个动态链接库被链接到一个程序文件中的时候,最后的程序文件并不包括动态链接库中的代 码,而仅仅包括对动态链接库的引用,并且不保存动态链接库的全路径,仅仅保存动态链接库的 名称。动态链接库就是第三种类型,共享对象文件

基于动态连接库创建出来的二进制文件格式还是ELF,但是稍有不同。首先,多了一个.interp的Segment,这里面是ld-linux.so,这是动态链接器,也就是说,运行时的链接动作都是它做的。另外,ELF文件中还多了两个section,一个是.plt,过程链接表(Procedure Linkage Table, PLT),一个是.got.plt,全局偏移量表(Global Offset Table,GOT)

比如对于dynamiccreateprocess这个程序要调用libdynamicprocess.so里的create_process函数。由于是运行时才去找,编译的时候,压根不知道这个函数在哪里,所以就在PLT里面建立一项 PLT[x]。这一项也是一些代码,有点像一个本地的代理,在二进制程序里面,不直接调用 create_process函数,而是调用PLT[x]里面的代理代码,这个代理代码会在运行的时候找真正的 create_process函数。而代理代码就是用到了GOT这里面也会为create_process函数创建一项GOT[y]。这一项是运行时create_process函数在内存中真正的地址。

对于GOT怎么直到create_process函数在内存中真正的地址?一开始创建了GOT[y]里面是空的,他调用plt[0],PLT[0]转而调用GOT[2],这里面是是ld-linux.so的 入口函数,这个函数会找到加载到内存中的libdynamicprocess.so里面的create_process函数的地址,然后把这个地址放在GOT[y]里面。

运行程序为进程

上面讲完了ELF格式,生成ELF文件之后还是个程序,那怎么把这个文件加载到内存里面呢?在内核中,有这么一个数据结构用来定义加载二进制文件的方法

struct linux_binfmt {struct list_head lh;struct module *module;int (*load_binary)(struct linux_binprm *);int (*load_shlib)(struct file *);int (*core_dump)(struct coredump_params *cprm);unsigned long min_coredump; /* minimal dump size */
} __randomize_layout;

对于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,
};

原理exec这个系统调用最终调用的load_elf_binary

进程树

既然所有的进程都是从父进程fork过来的,那总归有一个祖宗进程,这就是咱们系统启动的init进程。在解析Linux的启动过程的时候,1号进程是/sbin/init。如果在centOS 7里面,我们ls一下,可 以看到,这个进程是被软链接到systemd的。PID 1的进程就是我们的init进程systemd,PID 2的进程是内核线程kthreadd,这两 个我们在内核启动的时候都见过。其中用户态的不带中括号,内核态的带中括号。

总结

对高级编程语言,比如对C语言:

1、我们先将文件编译成so文件和可执行文件,放在硬盘上。

2、用户态的进程A执行fork(),创建进程B。

3、在进程B的处理逻辑中,执行exec系列系统调用,这个系统调用会通过load_elf_binary方法,将刚才生成的可执行文件,加载到进程B的内存中执行。

Linux:公司这么多项目,怎么管相关推荐

  1. Linux服务器配置与管理项目教程(CentOS7 /RHEL 7)(第三版)题库带答案

    Linux服务器配置与管理项目教程 (CentOS7 /RHEL 7)(第三版)微课版 第1篇   系统安装与网络配置 项目1  安装CentOS 服务器 项目2  配置Linux基础网络 不积跬步, ...

  2. 如何凭本事搞砸公司的重大项目?

    点击上方蓝色"方志朋",选择"设为星标"回复"666"获取独家整理的学习资料! 技术圈有句老话,凭运气接来的项目,都会凭本事搞砸.老K经常告 ...

  3. linux npm安装_怎样在Linux上开发vue项目

    怎样在Linux上开发vue项目 一.开发环境搭建:安装node.js环境以及vue cli工具 (1)安装node.js 从官网下载对应的二进制压缩包,如下图: 解压到程序安装目录 xz -d no ...

  4. Linux下 SpringBoot jar项目后台运行、查看、停用

    运行java jar: nohup java -jar **-0.0.1-SNAPSHOT.jar & 查看进程: 采用top或者ps aux命令.一般 如果后台是springboot,jar ...

  5. linux上传github项目

    重温linux上传github项目的几个步骤,前提是linux上部署了git. 1)github线上创建一个Repositories,项目名和线下项目一致. 2)linux线下切换到项目下,初始化为g ...

  6. linux 系统网络服务器组建,配置和管理实训教程 pdf,Linux网络服务器配置管理项目实训教程2...

    Linux网络服务器配置管理项目实训教程2 附录2 Linux常用命令 在文本模式和终端模式下,经常使用Linux命令来查看系统的状态和监视系统的操作,如对文件和目录进行浏览.操作等.在Linux较早 ...

  7. linux是基于什么的软件模式进行发布的,《Linux操作系统与应用项目教程》习题.doc...

    <Linux操作系统与应用项目教程>习题 1.8 练习题 一.填空题 1.GUN的含义是 . 2.Linux一般有3个主要部分: . . . 3.目前被称为纯种的Unix指的就是 以及 这 ...

  8. linux上运行项目,发布项目到 Linux 上运行 Core 项目

    目录索引 简介 ASP.Net Core 给我们带来的最大的亮点就是跨平台,我在我电脑(win7)上用虚拟机建了个 CentOS7 ,来演示下,我们windows上的项目如何发布项目到Linux上运行 ...

  9. linux部署项目文档,Linux上部署综合项目专业资料.doc

    LINUX上布署项目过程 1 准备工作 1.下载安装Xshell.Xftp(用于远程连接Linux主机,具体自行baidu) 2.官网下载Linux下tomcat安装包,我用是: apache-tom ...

  10. 控制台应用和空项目有什么区别_在公司做的项目和自己在学校做的有什么区别?...

    前言 只有光头才能变强. 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 不知道大家还是学生的时候有没有这个问题:公司做的项目 ...

最新文章

  1. Java实现无向图的邻接列表表示,深度遍历及广度遍历
  2. php错误密码也能登陆账号,php用户登陆代码(限制用户错误登录次数)(1/2
  3. 安装python3.7和PyCharm专业版
  4. PHP——获取上传文件的后缀名
  5. JProfiler 11中文版
  6. Linuc C 编程实例1
  7. 协议簇:TCP 解析: 连接断开
  8. web前端之HTML
  9. WPF仿微软事件和属性窗体,效果更炫!
  10. 电脑键盘灯怎么打开_电脑开机后黑屏键盘灯也不亮,教你一招搞定 建议收藏...
  11. 揭晓:为什么建议每个开发人员都学Python?
  12. python期权价格计算器_使用Python构建内在价值计算器
  13. 微信营销十一(微信公众号吸粉技巧)
  14. 党政信创建设进入新发展阶段的三大趋势
  15. Delphi 生成二维码【PaintBox】并保存为本地文件添加至【Image】控件中
  16. 智遥工作流将数据导出到Excel分析
  17. 焦虑症和抑郁症有什么区别吗?
  18. 英特尔平台安装黑苹果
  19. C语言 指向函数的指针
  20. 第十二期基金定投-周末更新数据

热门文章

  1. react fiber架构学习
  2. floyd算法-matlab
  3. 华为交换机堆叠连线方法
  4. 荣耀鸿蒙系统手机更新名单,华为鸿蒙系统开放升级,荣耀手机公布名单,18款领衔更新...
  5. Vue脚手架的使用(Vue CLI)
  6. Baklib客户故事:快递助手ERP
  7. FIR滤波器的Verilog实现
  8. linux修改文件或目录的所有者(chown)和用户组(chgrp)
  9. 解析SQL中内连接、外连接、完全连接、笛卡尔积关系
  10. mac系统安装nacos,详细图文教程,解决启动不了nacos