linux内核阅读感悟,读Kernel感悟-Linux内核启动-从hello world说起
内核是从哪里开始执行的呢?几乎任何一本源代码分析的书都会给出详细的答案。不过,我试图从一个不同的角度(一个初学者的角度)来叙述,而不是一上来就给出答案。从熟悉的事物入手,慢慢接近陌生的事物,这是比较常见的思路。既然都是二进制代码,那么不妨从最简单的用户态C程序,hello world开始。说不定能找到共同点。恰好我是一个喜欢寻根究底的人。也许,理解了hello world程序的启动过程,有助于更好地理解内核的启动。
好,开始寻根究底吧。从普通的C语言用户态程序开始写。先写一个简单的hello world程序。
/*helloworld.c*/
#include
int main()
{
printf("hello world\n");
return 0;
}
然后gcc helloworld.c -o helloworld,一个最简单的hello world程序出现了。
它是从哪里开始执行的呢?这还不简单?main函数么。地球人都知道。
为什么一定要从main函数开始呢?于是,我开始琢磨这个hello world程序。
file helloworld可知,它是一个elf可执行文件。
反汇编试试。
objdump -d helloworld
反汇编的结果令人吃惊,因为出现了_start()等一堆函数。一定是gcc编译时默认链接了一些库函数。
其实,只要运行gcc -v helloworld.c -o helloworld就会显示gcc详细的编译链接过程。其中包括链接/usr/lib/下的crti.o crt1.o crtn.o等等文件。用objdump查看,_start()函数就定义在crt1.o文件中。
那么helloworld的真正执行的入口在哪里呢?我们可以使用readelf来查看,看有没有有用信息。
readelf -a helloworld
helloworld作为一个elf文件,有elf文件头,section table和各个section等等。有兴趣可以去看看elf文件格式的文档。
用readelf可知,在helloworld的elf文件头的信息中,有这么一项信息:
入口点地址: 0x80482c0
可见,helloworld程序的入口地址在0x80482c0处,而由objdump得:
080482c0 :
可见,_start()是helloworld程序首先执行的函数。_start()执行完一些初始化工作后,经过层层调用,最终调用main().可以设想,如果_start()里最终调用的是foo(),那么C程序的主函数就不再是main(),而是foo()了。
再进一步:helloworld程序具体是如何执行的呢。我们只能猜测是由bash负责执行的。然而具体看bash代码就太复杂了。我们可以用strace跟踪helloworld的执行。
strace ./helloworld
出来一大堆函数调用。其中第一个是execve().这是一个关键的系统调用,它负责载入helloworld可执行文件并运行。其中有很关键的一步,就是把用户态的eip寄存器(实际上是它在内存中对应的值)设置为elf文件中的入口点地址,也就是_start()。具体可见内核中的sys_execve()函数。
由此可见,程序从哪里开始执行,取决于在刚开始执行的那一刻的eip寄存器的值。而这个eip是由其它程序设置的,在这里,eip是由Linux内核设置的。具体过程如下:
1.用户在shell里运行./helloworld。
2.shell(这里是bash)调用系统调用execve()。
3.execve陷入到内核里执行sys_execve(),把用户态的eip设置为_start()。
4.当系统调用执行完毕,helloworld进程开始运行时,就从_start()开始执行
5.helloworld进程最后才执行到main()。
参考:elf文件格式
linux内核阅读感悟,读Kernel感悟-Linux内核启动-从hello world说起相关推荐
- linux工作原理fiq,读Kernel感悟-Linux内核启动-内核的生成 - kernel hacker 修炼之道——李万鹏 - 博客频道 - CSDN...
这段时间在看<源代码情景分析>,顺便写了一些感悟,去看小游戏http://www.qukan.net/.读内核源代码是一件很有意思的事.它像一条线,把操作系统,编译原理,C语言,数据结构与 ...
- linux 电子书阅读器_3个适用于Linux桌面的电子书阅读器
linux 电子书阅读器 我通常会在手机或Kobo电子书阅读器上阅读电子书. 我从来都不习惯在大屏幕上读书. 但是,许多人经常在笔记本电脑或台式机上读书. 如果您是其中之一(或者可能是),我想向您介绍 ...
- linux 内核调试 booting the kernel.,Uncompressing Linux...done, booting the kernel解决办法
u-boot是好的,是刚移植成功的,用其他的内核跑过没问题.所以皇莡-boot传参有问题,问题就是出在我移植的内核上面. 我用的是mini2440的配置,linux2.6.35的内核.网上找了很多资料 ...
- linux 内核调试 booting the kernel.,Uncompressing Linux....... done, booting the kernel就不动了的一个可能原因...
最近搞阳初2410的板子,做的U-BOOT1.2.0能从NAND FLASH启动起来了,但是引导内核真是搞怪,前几天还能引导的,这几天又不能引导了,但是这些内核用VIVI都是能引导的,搞得头痛死了,总 ...
- linux利用内存加快读盘速度,Linux性能优化从入门到实战:10 内存篇:如何利用Buffer和Cache优化程序的运行效率?...
缓存命中率 缓存命中率,是指直接通过缓存获取数据的请求次数,占所有数据请求次数的百分比,可以衡量缓存使用的好坏.命中率越高,表示使用缓存带来的收益越高,应用程序的性能也就越好. 实际上,缓存是现在所有 ...
- python怎么重新启动内核_通过“ipython kernel”重新启动ipython内核
我有一个ipython内核通过ipython kernel 这使我可以选择从不同的客户机(控制台.qtconsole甚至通过ssh从其他机器)连接到这个内核.在 最简单的情况是通过以下方式进行本地连接 ...
- linux内核 阅读,Linux内核阅读感悟
<Linux内核阅读感悟>由会员分享,可在线阅读,更多相关<Linux内核阅读感悟(261页珍藏版)>请在人人文库网上搜索. 1.contents表格我读了你的想法.2读核感悟 ...
- linux重复文件管理,在windows下解压缩Linux内核源代码出现重复文件原因
在windows下解压缩Linux内核源代码出现重复文件原因 2009年06月30日 13:35 来源:ChinaUnix博客 作者:embededgood 编辑:周荣茂 原因一.因为在Lin ...
- 【Linux】一步一步学Linux系统编程教程汇总(暂时暂停更新......)
00. 目录 文章目录 00. 目录 01. 概述和标准 02. 文件操作 03. 进程概念 04. 进程间通信 05. 多线程 06. 信号 07. 同步与互斥 08. 高级IO 09. 其它 10 ...
最新文章
- 永远的Hello World
- Spring Boot 中使用 Swagger2 构建强大的 RESTful API 文档
- 云图说丨“真人?机器?傻傻分不清!” WAF Bot管理,带你慧眼辨“精”!
- mysql5.5主从同步复制配置
- 自动化测试工具selenium 之Selenium-IDE
- 2020年接近尾声,我选择来鲲鹏开发者技术峰会学点干货!
- 【POJ】【3164】Commond Network
- StyleCop学习笔记——初识StyleCop
- 数据库备份与还原的过程中介质集有2个介质簇,但只提供了1个。必须提供所有成员...
- 面试题——内网相关(一)
- Python脚本自动化运维网络设备
- 性能优化:空间换时间
- NEUQOJ 1999: 三角形or四边形?【搜索联通块/模拟】
- 支付宝账号转账/扫码即可到转账页
- e.target.dataset和e.currentTarget.dataset
- 聊聊接口性能优化的11个小技巧
- 智能井盖被纳入《城市综合管廊运营服务规范》国标,喜大普奔
- 用Python实现原生爬取某牙直播平台数据
- 挖个冰块就能修自己!用「冰」做的科考机器车
- 慢SQL!压垮团队的最后一根稻草!