linux内核学习笔记(一)——内核体系结构
文章目录
Linux进程控制
系统最多可以有64个进程同时运行,除第一个进程为手工建立,其他进程均使用系统调用fork创建。
内核使用进程标识号(process ID,pid)标识进程。
进程由可致性的指令代码、数据和堆栈区组成。
任务数据结构
内核通过进程表对进程进行管理,每个进程在进程表中占有一项,进程表项是一个task_struct
任务结构指针,定义在include/linux/sched.h
中。
当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。
进程运行状态
一个进程在其生存期内,可处于一组不同的状态下,称为进程状态。
-
运行状态(
TASK_RUNNING
)当进程正在被CPU执行,或已经准备就绪随时可由调度程序执行,则称该进程处于运行状态(running)。当系统资源已经可用时,进程就被唤醒而进入准备运行状态,该状态被称为就绪态
-
可中断睡眠状态(
TASK_INTERRUPTIBLE
)当进程处于可中断状态时,系统不会调度该进程执行。当系统产生一个终端或者释放进程正在等待的资源,或者进程收到一个信号,都可以唤醒进程转换到就绪状态(运行状态)
-
不可中断睡眠状态(
TASK_UNINTERRUPTIBLE
)与可中断睡眠状态类似。但处于该状态的进程只有被使用wake_up()函数明确唤醒时才能转换到可运行的就绪状态。
-
暂停状态(
TASK_STOPPED
)当进程收到信号SIGSTOP、SIGTSTP、SIGTTIN和SIGTTOU时就会进入暂停状态。可向其发送SIGCONT信号让进程转换到可运行状态。
-
僵死状态(
TASK_ZOMBIE
)当进程已经停止运行,但其父进程还没询问其状态时,则称该进程处于僵死状态
只有当进程从“内核运行态”转移到“睡眠状态”时,内核才会进行进程切换操作。在内核态下运行的进程不能被其他进程抢占,而且一个进程不能改变另一个进程的状态。为了避免切换时造成内核数据错误,内核在执行临界区代码时会禁止一切中断。
进程调度
Linux进程是抢占式的,被抢占的进程仍然处于TASK_RUNNING
状态,只是暂时没有被CPU运行,进程的抢占发生在进程处于用户态执行阶段,在内核态执行时是不能被抢占的。Linux 0.11中采用基于优先级排队的调度策略。
对内存的使用方法
- 逻辑地址(Logical Address)是指程序产生的与段相关的偏移地址部分。
- 线性地址(Linear Address)是逻辑地址到物理地址变换之间的中间层。
- 物理地址(Physical Address)是指出现在CPU外部地址总线上的寻址物理内存的地址信号,是地址变换的最终结果地址。
- 虚拟内存(Virtual Memory)是指计算机呈现出要比实际拥有的内存大得多的内存量。
Linux内核源代码的目录结构
引导启动程序目录boot
boot目录包含3个汇编文件,是内核源代码文件中最先被编译的程序
- bootsect.s : 磁盘引导块程序,编译后会驻留在磁盘的第一个扇区中
- setup.s : 用于读取机器的硬件配置参数,并把内核模块system移动到适当的内存位置处
- head.s : 会被编译连接在system模块的最前部分,主要进行硬件设备的探测设置和内存管理页面的初始设置工作
文件系统目录fs
图中每个方框代表一个文件,从上到下按基本引用关系放置,虚框中的程序文件不属于文件系统,带箭头的线条表示引用关系,粗线条表示有相互引用关系。
文件系统目录中可以划分为四个部分:高速缓冲区管理、低层文件操作、文件数据访问和文件高层函数。
管理高速缓冲区的程序是buffer.c,其他程序则主要用于文件系统管理。
在file_table.c中,目前只定义了一个文件句柄(描述符)结构数组。
ioctl.c文件将引用kernel/chr_drv/tty_ioctl.c中的函数,实现字符设备的io控制功能。
exec.c主要包含一个执行程序函数do_execve()
,它是所有exec()
函数簇中的主要函数。
fcntl.c程序用于实现文件i/o控制的系统调用函数。
read_write.c程序用于实现文件读/写和定位三个系统调用函数。
stat.c程序中实现了两个获取文件状态的系统调用函数。
open.c程序主要包含实现修改文件属性和创建与关闭文件的系统调用函数。
char_dev.c主要包含字符设备独写函数rw_char()
。
pipe.c程序中包含管道读写函数和创建管道的系统调用。
file_dev.c程序中包含基于i几点和描述符结构的文件独写函数。
namei.c程序主要包括文件系统中目录名和文件名的操作函数和系统调用函数。
block_dev.c程序包含块数据读和写函数。
inode.c程序中包含针对文件系统i节点操作的函数。
truncate.c程序用于在删除文件时释放文件所占用的设备数据空间。
bitmap.c程序用于处理文件系统中i系欸但和逻辑数据块的位图。
super.c程序中包含对文件系统超级块的处理函数。
头文件目录include
头文件目录中一共含有32个.h头文件。主目录下13个,asm目录下4个,linux目录中有10个,sys子目录中有5个。
内核初始化程序目录init
用于执行内核所有的初始化工作,然后移到用户模式创建新进程,并在控制台设备上运行shell程序。
内核程序主目录kernel
内核库函数目录lib
内核库函数用于为内核初始化程序init/main.c运行在用户态的进程(进程0、1)提供调用支持,与普通静态库的实现方法完全一样。
内存管理程序目录mm
主要用于管理程序对主内存区的使用,实现了进程逻辑地址到线性地址以及线性地址到主内存区中物理内存地址的映射,通过内存的分页管理机制,在进程的虚拟内存页与主内存区的物理内存页之间建立了对应关系。
编译内核工具程序目录tools
用于将Linux各个目录中被分别编译生成的目标代码连接合并成一个可运行的内核映像文件image。