一、获取内核源码
1. Git
git实际上是一种开源的分布式版本控制工具。
-
Linux作为一个开源的内核,其源代码也可以用git下载和管理
- 获取最新提交到版本树的一个副本
- $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
- 下载代码后,更新自己的分支到最新分支
- $ git pull
2.安装内核源代码
压缩形式为bzip2:
$ tar xvjf linux-x.y.z.tar.bz2
-
压缩形式为zip:
$ tar xvzf linux-x.y.z.tar.gz
关于参数:
-x 解开.tar格式的文件
-v 显示详细信息
-j 使用bzip2程序
-z 使用gzip程序
-f 使用归档文件
3. 使用补丁
从内部源码树开始,运行$ patch -p1 < ../patch-x,y,z
二、内核源码结构
详见LINUX内核分析第三周学习总结:构造一个简单的LINUX系统MENUOS中第一部分:“Linux内核源码简介”。
目 录 | 描 述 |
---|---|
arch | 特定体系结构的代码 |
block | 块设备I/O层 |
crypo | 加密API |
Documentation | 内核源码文档 |
drivers | 设备驱动程序 |
firmware | 使用某些驱动程序而需要的设备固件 |
fs | VFS和各种文件系统 |
include | 内核头文件 |
init | 内核引导和初始化 |
ipc | 进程间通信代码 |
kernel | 像调度程序这样的核心子系统 |
lib | 同样内核函数 |
mm | 内存管理子系统和VM |
net | 网络子系统 |
samples | 示例,示范代码 |
scripts | 编译内核所用的脚本 |
security | Linux 安全模块 |
sound | 语音子系统 |
usr | 早期用户空间代码(所谓的initramfs) |
tools | 在Linux开发中有用的工具 |
virt | 虚拟化基础结构 |
- COPYIN:内核许可证
- CREDITS:开发者列表
- MAINTAINTERS:维护者列表(维护内核子系统和驱动程序)
三、编译内核
1. 配置内核(关于make与config)
(1)相关
- Makefile:根据配置的情况,构造出需要编译的源文件列表,然后分别编译,并把目标代码链接到一起,最终形成 Linux 内核二进制文件。
- config.in:内核配置文件,给用户提供配置选择的功能。
- 配置工具:包括配置命令解释器(
make config
)和配置用户界面(例如:make menuconfig
:基于ncurse库的图形界面工具;make gconfig
:基于gtk+的图形工具...)。 - .config:用户用来存放内核配置后结果的文件。
- 可以配置的各种选项:用CONFIG_FEATURE形式表示,其前缀为CONFIG。
(2)命令
- make config:遍历所有配置项,并让用户选择
- make deconfig:按默认的配置
- make oldconfig:先将
/boot
目录下的配置文件写进.config
文件中,采用的是注释的形式写进新增加的功能。 - zcat /proc/config.gz > .config:配置选项
CONFIG_IKCONFIG_PROC
会把完整的压缩过的内核配置文件存放在/proc/config.gz
中,再次编译时可以方便地克隆当前的配置。 - make:默认的Makefile自动化编译。
2. 其它事项
-
减少垃圾信息
$ make > ../detritus
#将错误报告和警告信息重定向到文件中
$ make > /dev/null
#将无用的输出信息重定向到/dev/null中 - /dev/null:空设备,输入的信息直接丢弃 -
衍生多个编译作业:make程序能把编译过程拆分成多个并行的作业。其中每个作业独立并发地运行,有助于加快多处理器系统上的编译过程,也有利于改善处理器的利用率。默认情况下,make只衍生一个作业。
$ make -jn
#以多个作业编译内核 - j:指定同时执行多任务
- n:要衍生出的作业数
3. 安装新内核
make modules_install
#把所有已编译的模块安装到正确的主目录/lib/modules下
- System.map文件:编译时在内核代码树的根目录下创建的
符号对照表
。用来将内核符号与它们的起始地址对应起来。
四、内核开发特点
1. 无libc库/标准头文件
原因:(速度与大小)保证内核高效和简练。
-
内核源代码文件不能包含外部头文件。
- 基本头文件:内核源代码*目录下的
include
中 - 体系结构相关头文件:内核源代码树的
arch/<architecture>/include/asm
目录下
- 基本头文件:内核源代码*目录下的
printk()函数:把格式化好的字符串拷贝到内核日志缓冲区上,syslog程序可以通过读取该缓冲区来获取内核信息。
2. 必须使用GNU C
什么是GNU?GNU是一种操作系统,GNU提供的C编译器就是我们之前使用的gcc。
(1)内联函数
static inline void wolf(unsigned long tail_size);
- static:关键字
- inline:用于限定关键字
-
内联函数:编译时在它被调用的地方展开。
- 优点:减少了函数调用的开销,性能较好。
- 缺点:频繁的使用内联函数也会使代码变长,从而在运行时占用更多的内存。
定义内联函数特点:时间要求高,本身长度较短的函数。
使用之前就要定义好内联函数,一般在头文件中定义。
为了类型安全和易读性,优先使用内联函数而不是复杂的宏。
(2)内联汇编
unsigned int low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
/* low 和 high 分别包含64位时间戳的低32位和高32位 */
- asm:嵌入汇编代码
- volatile:不优化
- 汇编语言用于偏近底层或对执行时间严格要求的地方。
(3)分支声明
/* 如果error在绝大多数情况下为0(假) */
if (unlikely(error)) {
/* ... */
}
/* 如果success在绝大多数情况下不为0(真) */
if (likely(success)) {
/* ... */
}
- 对于条件选择语句,在一个条件经常/很少出现时,编译器可通过gcc内建的一条指令对条件分支选择进行优化。
- 内核把这条指令封装成了宏。
3. 没有内存保护机制
- 内核自己非法访问内存的风险
- 内核中的内存都不分页:每用掉一个字节,物理内存都减少一个
4. 难以执行浮点运算
- 使用浮点数时,需要人工保存和恢复浮点寄存器及其他一些繁琐的操作。
- 不建议使用
5. 每个进程只有一个很小的定长堆栈
- 内核栈的大小是编译内核时决定的,对于不用的体系结构,内核栈的大小不一样,但都是固定的。(不像用户空间的栈可以动态增长)
6. 必须时刻注意同步和并发
-
原因:
- Linux是抢占多任务操作系统
- 内核支持对称多处理器系统(SMP)
- 中断异步到来
- 内核可以抢占
常用解决方法:自旋锁和信号量
7. 考虑可移植性的重要性
- 需要保持的特点:大部分C语言代码与体系结构无关。
五、总结:关于Linux内核的结构与特点
1. 版本控制
- 我最早接触git是刚开始使用实验楼的时候,实验楼中的代码保存需要用到其中“我的代码库”功能,实际上就是最简单的git。
- Linux内核这种开源的代码以及很多项目使用git进行版本控制与协作都是挺方便的。
- 网上有很多教程可以参考,感觉这个比较全面:Git教程,可以在一些网站上创建自己的代码库,比如:git.oschina,操作过就会发现还是比较简单的。
2. 依据结构和特点的开发
- 通读本章之后感觉Linux内核的很多要求与一般的项目其实是差不多的,它的这些基本结构、开发的特点,对于理解它各个部分的工作过程是很有帮助的。
参考资料1:《Linux内核设计与实现》(原书第三版)
参考资料2:make config 解惑
《Linux内核设计与实现》读书笔记 第二章 从内核出发的更多相关文章
-
Linux内核设计与实现 读书笔记 转
Linux内核设计与实现 读书笔记: http://www.cnblogs.com/wang_yb/tag/linux-kernel/ <深入理解LINUX内存管理> http://bl ...
-
Linux内核设计与实现 读书笔记
第三章 进程管理 1. fork系统调用从内核返回两次: 一次返回到子进程,一次返回到父进程 2. task_struct结构是用slab分配器分配的,2.6以前的是放在内核栈的栈底的:所有进程的ta ...
-
STL源码分析读书笔记--第二章--空间配置器(allocator)
声明:侯捷先生的STL源码剖析第二章个人感觉讲得蛮乱的,而且跟第三章有关,建议看完第三章再看第二章,网上有人上传了一篇读书笔记,觉得这个读书笔记的内容和编排还不错,我的这篇总结基本就延续了该读书笔记的 ...
-
Spring 3.x 实践 第一个例子(Spring 3.x 企业应用开发实战读书笔记第二章)
前言:工作之后一直在搞android,现在需要更多和后台的人员交涉,技术栈不一样,难免鸡同鸭讲,所以稍稍学习下. 这个例子取自于<Spring 3.x 企业应用开发实战>一书中的第二章,I ...
-
Getting Started With Hazelcast 读书笔记(第二章、第三章)
第二章 起步 本章就相当简单粗暴了,用一个个例子说明hazelcast怎么用. 1.map,set,list这些集合类都是开箱即用的,只要从Hazelcast的实例中获取一份就行. 2.增加了Mult ...
-
Java Concurrency in Practice 读书笔记 第二章
第二章的思维导图(代码迟点补上):
-
javascript 数据结构和算法读书笔记 >; 第二章 数组
这章主要讲解了数组的工作原理和其适用场景. 定义: 一个存储元素的线性集合,元素可以通过索引来任意存取,索引通常是数字,用来计算元素之间存储位置的偏移量. javascript数组的特殊之处: jav ...
-
《C++ Primer》读书笔记—第二章 变量和基本类型
声明: 文中内容收集整理自<C++ Primer 中文版 (第5版)>,版权归原书所有. 学习一门程序设计语言最好的方法就是练习编程. 1.8比特的char类型计算机表示的实际范围是-12 ...
-
[Effective Java 读书笔记] 第二章 创建和销毁对象 第一条
第二章 创建和销毁对象 第一条 使用静态工厂方法替代构造器,原因: 静态工厂方法可以有不同的名字,也就是说,构造器只能通过参数的不同来区分不同的目的,静态工厂在名字上就能表达不同的目的 静态工厂方法 ...
随机推荐
-
[Java coding] leetcode notes
1, 如何不排序而找到最大,次大或者最小值? var int max1, max2, min1; iterate array once: update max1, max2, min1, for ex ...
-
使用Xcode6和IOS8SDK以后遇到的问题
定位.苹果在IOS8里面修改了定位授权协议,也就意味着你原来的app在ios8上很可能无法定位.目前最好的办法就是在app启动的时候调用IOS8的定位授权API来获取用户的授权,这样就不要在其他地方做 ...
-
android19以上和以下uri转路径的方法
android 19以上 /** * 专为Android4.4以上设计的从Uri获取文件路径 */ public static String getPath(final Context context ...
-
Android 高仿腾讯旗下app的 皮肤加载技术
http://www.cnblogs.com/punkisnotdead/p/4968851.html 以前写的这篇文章 可以高仿出 知乎 新浪微博等 绝大多数app的换肤技术,但是遗漏了腾讯的效果, ...
-
uva 10910
简单dp /************************************************************************* > Author: xlc2845 ...
-
== 和 equal
==比较是地址 equal比较的是值 Integer r1 = new Integer(900);//定义r1整型对象 Integer r2 = new Integer(900);//定义r2整型对象 ...
-
No matching authentication protocol
java 连接oracle数据库: 之前连接公司的oracle数据库没有问题,但客户提供的是oracle12C版本的,连接就报 :No matching authentication protocol ...
-
SpringBoot 使用validation数据校验
后端对数据进行验证 添加包 hibernate-validator <!-- https://mvnrepository.com/artifact/org.hibernate.validator ...
-
2019-03-27-day020-单继承与多继承
昨日回顾 类的加载顺序 类内部的代码什么时候执行? 除了方法里面的代码 其余的所有内容都是在执行这个文件的时候就从上到下依次执行的 不需要调用 如果有同名的方法.属性,总是写在后面的会生 class ...
-
Codeforces Round #313 D. Equivalent Strings(DFS)
D. Equivalent Strings time limit per test 2 seconds memory limit per test 256 megabytes input standa ...