内核源码树
arch 特定体系结构的源码
block Crypto API
crypto 内核源码文档
drivers 设备驱动程序
firmware
fs VFS和各种文件系统
include 内核头文件
init 内核引导和初始化
ipc 进程间通信代码
kernel 像调度程序这样的核心子系统
lib 通用内核函数
Makefile
Makefile.common
mm 内存管理子系统和VM
Module.symvers
net 网络子系统
samples
scripts 编译内核所用的脚本
security Linux安全模块
sound 语音子系统
System.map
tools
usr 早期用户空间代码
virt
编译内核
配置内核(不同的选项)
make config
make menuconfig
make xconfig
make gconfig
创建默认配置
make defconfig
make oldconfig
编译
make
记录编译信息
make >../log.txt
忽略编译信息
make >/dev/null
衍生多个编译作业
make -j[任务数量]
如双核处理器上,每个处理器衍生两个作业
make -j4
安装内核
把arch/i386/boot/bzImage拷贝到/boot
依照vmlinuz-version来命名
编辑/boot/grub/grub.conf文件,为新内核建立新的启动项
使用LILO的系统则编辑/etc/lilo.conf,然后运行lilo
安装模块
make modules_install
内核开发的特点
- 没有libc库
大部分常用的C库函数在内核中都已经得到了实现
- GNU C
内联函数
把对时间要求比较高而本身长度又比较短的函数定义成内联函数
1 | static inline void test(unsigned long tail_size) |
内联函数必须在使用前就定义好,一般在头文件或者文件头中定义内联函数。
内联汇编
分支声明(为了优化)
1 | likely() |
- 没有内存保护机制
- 不要轻易在内核中使用浮点数
- 内核空间具有容积小而固定的栈
- 同步和并发
- 可移植性
进程管理
进程是处于执行期的程序以及它所包含的资源的总称
- 进程描述符及任务结构
内核把进程存放在任务队列中。任务队列是各双向循环链表,链表中的每一项都是类型为task_struct,称为进程描述符的结构,定义在<linux/sched.h>文件中。
进程描述符中包含一个具体进程的所有信息
task_struct在32位机器上有1.7k字节,其中包含的数据能完整的描述一个正在执行的程序。(打开的文件,进程的地址空间,挂起的信号,进程的状态还有其他更多信息)
- 分配进程描述符
通过slab分配器分配task_struct结构
- 进程描述符的存放
内核通过一个唯一的进程标识值或PID类标识每个进程,PID最大默认值为32768(short int的最大值),可以修改/proc/sys/kernle/pid_max来提高上限。
- 进程状态
进程描述符中的state域描述了进程的当前状态,系统中每个进程都必须处于五种状态中的一种。
- TASK_RUNNING(运行)
- TASK_INTERRUPTIBLE(可中断)
- TASK_UNINTERRUPTIBLE(不可中断)
- TASK_ZOMBIE(僵死)
- TASK_STOPPED(停止)
- 设置当前进程状态
1 | set_task_state(task,state); |
- 进程上下文
进程家族树
所有的进程都是PID为1的init进程的后台
内核在系统启动的最后阶段启动init进程,该进程读取系统的初始化脚本并执行其他的相关程序
进程间的关系存放在进程描述符中,每个tack_struct都包含一个指向其父进程task_struct,叫做parent的指针
获取其父进程的进程描述符:
1 | struct task_struct *my_parent = ourrent->parent; |
访问子进程:
1 | struct task_struct *task; |
系统调用
API.POSIX.C
系统调用(系统调用号)
系统调用处理程序
int $0x80(十进制128) system_call()
第128号异常处理程序
系统调用号通过eax寄存器传递给内核
call *sys_call_table(,%eax,4)
系统调用表的表项是以32位类型存放的,所以内核需要将给定的系统调用号乘以4,然后查询
参数传递:ebx,ecx,edx,esi和edi按照顺序存放前五个参数系统调用的实现
系统调用上下文
- entry.s(系统调用表)
中断和中断处理程序
- IRQ:中断请求
- ISR:中断服务例程
注册中断处理程序
1 | //request_irq()成功执行会返回0 |