IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 从一个ELF程序的加载窥探操作系统内核-(5) -> 正文阅读

[系统运维]从一个ELF程序的加载窥探操作系统内核-(5)

从一个ELF程序的加载窥探操作系统内核-(5)

操作系统加载一个ELF程序看似一个EASY的动作,其实下面隐藏了很多很多OS内核的关键实现,让我们一起来解密其中的流程

作者是一个micro kernel的开发者,在设计动态链接器的时候,在此留下一些笔记,重点参考了以下资料文献

  • 《程序员的自我修养》
  • 《深入理解计算机系统》
  • 《现代操作系统-原理与实现》
  • 《深入理解LINUX内核》
  • 《设计模式/JAVA》

LINUX下的ELF加载器究竟是如何完成的

ELF加载器其实和OS的实现是紧密捆绑在一起的,就像glibc捆绑了linux一样,可移植性是很差的

  • LINUX下的ELF加载流程如下
    在这里插入图片描述

当ELF程序需要解释器(动态链接器)的时候,LINUX内核只完成了初步的解析工作,剩下的工作就转给链接器去完成了,也就是大名鼎鼎的ld.so

Linux下一个最小程序,也必须包括ld.so和libc.so这两个动态库

  • ld.so看起来是个动态库,实际上他是静态的,这里说的静态指的是他的运行不依赖任何外部库,只是被编译成了PIC了,算作披着羊皮的狼吧。但是既然ld被编译成了动态库的形式,那么必然有重定位工作要做,也就是对自己的重定位,重定位后就可以正常使用ld.so内的函数和全局变量了
  • 有同学说既然是这样,为什么不直接编译静态库算了,链接器自举操作纯属脱了裤子放屁,归根结底还是为了节省内存罢了

glibc下的ld.so链接器流程如下
在这里插入图片描述
链接器最重要的工作就是映射依赖库以及重定位工作,映射工作主要依赖mmap这个系统调用,重定位是链接器最复杂的,里面的细节可以参考ELF加载器的原理与实现

  • 完成重定位工作后,最后一步将程序转移到crt,crt是一个C运行时环境,CRT有什么用呢?
  • 很多同学有疑问?既然链接器都完成了全部工作,不应该跳转到main去运行程序吗?实际上在执行main前我们还需要为main做一点准备工作,这个工作就是由CRT完成

CRT主要有两个工作

  1. 用户堆管理的初始化
    1. malloc用户进程的堆分配是放在libc里来完成的,但是这个内存管理器的初始化工作是在crt中完成的!
  2. 输入输出设备初始化
    1. 如果要使用printf,实际上最后调用的是write系统调用(fd=STDOUT=1),初始化stdin/stdout/stderr这三个全局变量和相关权限的工作是在crt中完成的

伪代码如下

extern int main(int argc, char *argv[]);
extern int crt_io_initialize(void);
extern int crt_heap_initialize(void);

void exit(int code)
{

}

int crt_main_entry(int argc, char **argv)
{
	int ret;

	/* 初始化IO资源管理器 */
	crt_io_initialize();

	/* 初始化进程堆管理器 */
	crt_heap_initialize();

	/* 跳转到main */
	ret = main(argc, argv);

	/* 进程退出 */
	//exit(ret);

	return ret;
}

简单看一下IO是如何初始化的

struct streamlist tg_streamlist;

#define STDIN_FILENO                       0       /* File number of stdin */
#define STDOUT_FILENO                    1       /* File number of stdout */
#define STDERR_FILENO                     2       /* File number of stderr */

#define stdin       (&tg_streamlist.sl_std[STDIN_FILENO])
#define stdout     (&tg_streamlist.sl_std[STDOUT_FILENO])
#define stderr      (&tg_streamlist.sl_std[STDERR_FILENO])

tg_streamlist.sl_std[0].fs_fd        = STDIN_FILENO;
tg_streamlist.sl_std[0].fs_oflags   = O_RDONLY;

tg_streamlist.sl_std[1].fs_fd        = STDOUT_FILENO;
tg_streamlist.sl_std[1].fs_oflags   = O_WROK | O_CREAT;

tg_streamlist.sl_std[2].fs_fd        = STDERR_FILENO;
tg_streamlist.sl_std[2].fs_oflags   = O_WROK | O_CREAT;

简单看一下用户堆是如何初始化的

先使用brk(0)确定heap的起始地址,然后默认分配132KB内存,再初始化具体的内存管理算法,glibc是ptmalloc,后面的malloc和free就由内存管理算法去分配与释放

int crt_heap_initialize(void)
{
	void *base = NULL;

	/* 参考linux分配超过128KB使用MMAP
	 * 默认大小为128KB(0x20000)
	 * 内存管理的数据结构本身还需占用空间,则扩容至132KB(0x21000)
	 */
	unsigned long heap_size = 132 * 1024;

	base = (void *)brk(0);
	if (!base) {
		return -1;
	}

	void *end = (void *)((unsigned long)base + heap_size);
	end = (void *)brk(end);
	if (!end) {
		return -1;
	}

	return mm_heap_initialize(base, heap_size);
}

看一下我们的ELF链接脚本该如何写

ENTRY(crt_main_entry);

SECTIONS
{
    . = 0x08040000;
    .text :
    {
        *(.text .text.*)
    }
    .rodata :
    {
        *(.rodata .rodata.*)
    }
	. = ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1));
    .data :
    {
        *(.data .data.*)
    }
	
    .bss :
    {
        *(.bss .bss.*)
    }
}

总结一下crt的流程

在这里插入图片描述

最后crt最后以crt.o的方式被链接到elf程序中

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 00:32:30  更:2022-04-01 00:34:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 23:35:42-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码