Linux系统概念模型与影响程序执行性能的因素分析
一、精简的Linux系统概念模型
(一)Linux系统模型
从整体而言,Linux系统分为用户空间和内核空间两部分。而完整的Linux内核运行于内核空间,它管理底层的所有硬件设备;同时也向用户提供系统调用接口来使用某些特权操作。
(二)Linux内核
Linux内核主要提供以下服务:系统调用接口、中断管理、进程管理、内存管理、文件系统以及硬件驱动程序。
1. 中断管理
(1)概念:因为某些原因,系统转去执行其他任务,待处理完毕后,如果能返回原来的任务,则返回继续执行原来的任务。
(2)类型:硬中断,软中断;硬中断是由硬件发出的,可以中断CPU的中断;软中断又分为故障和陷阱,都是由当前程序(指令)发出的,陷阱则是调用系统调用,故障则是当前程序出现了某些不可预期的错误(如除以0,段错误等等)
2. 系统调用接口
(1)概念:应用程序不可以直接使用或调度系统资源,因为如果每个进程都可以有权进行这样的操作,会出现不可预估的错误!所以,当程序需要这些资源时,可以通过系统调用从用户态进入内核态,由内核对操作系统的资源进行调配(例如malloc函数就是通过函数api来调用系统分配内存的system call)
3.进程管理
(1)进程的概念:进程是程序的执行过程,是动态的概念,由PCB所映射。
(2)进程的状态:创建态、就绪态、阻塞态、运行态、结束态(Linux下:等待态,运行态,睡眠态,僵死态)
(3)进程的切换:切换内核态的堆栈和保存当前进程的CPU上下文,然后加载需要切换的进程的内核堆栈以及它的上下文。
(4)调度时机:时间片用完;更高优先级抢占;系统调用返回用户态;中断处理后返回用户态
(5)调度算法:FIFO,RR(多了时间片的FIFO算法),NORMAL
4.内存管理
(1)在内核态申请分配内存,直接分配;在用户态申请分配内存,分配一个线性地址空间和使用权,待真正使用这块内存时,会发生缺页异常,然后进行真的分配
(2)父子进程的地址空间是一样的,采取写时复制的策略
5.文件系统
Linux下“一切皆文件”。所以所有的“文件”都可以用统一的接口(open,close,read,write)实现
6.硬件驱动程序
不同的硬件设备提供不同的驱动程序,以便于使用该硬件。
(三)常见的操作命令
-
-
ps -axj查看进程及其状态
-
getrusage检测缺页数量
-
df 查看磁盘空间大小
-
du查看文件和目录大小
-
top查看cpu占用高的进程pid
-
dmesg查看内核中的保存信息,可了解发生段错误的程序名称、发生段错误的内存地址、指令指针地址、堆栈指针地址、错误代码、错误原因等。
-
pwd显示绝对路径
-
gerp正则匹配
-
ld链接指令
-
objdump -t xxx.o 查看xxx.o的符号表(readelf)
-
readelf 重定位表的查看方法
-
ln p1 p2:p1指明一个现有的文件的路径名,p2指明新建立的硬链接的路径名;ln -s p1 p2 创建软连接
二、影响执行性能的因素
(一)可执行程序的’生成‘
在分析相关因素前,先把可执行程序的‘前世今生’给梳理了:
1.预处理
a.将所有引用的头文件打开插入到程序
b.将所有的宏进行替换
c.删除注释
d.将不进入的条件编译语句删除
Linux下命令:gcc -E x.c -o x.i,其中x.i就是经过预处理的c程序
2.编译
gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc把代码翻译成汇编语言。
Linux下命令:gcc -S x.i -o x.s,其中x.s就是经过编译后的汇编语言文件
3.汇编
把汇编代码变成可以执行的机器语言
Linux下命令 gcc -C x.s -o x.o,其中x.o就是经过汇编后的机器语言文件,其中该文件由段组成,至少有两个段:代码段(包含的主要是程序的指令,分为可读和可执行),数据段(存放程序中用到的各种全局变量或静态的数据)
4.链接
将有关的目标文件彼此相连接(例如程序中可能调用了某个库文件中的函数,或者某个源文件中调用了另一个源文件中的函数等等)
a.静态链接:每个可执行程序中对所需要的目标文件都有一份副本,如果多个程序对同一个目标文件都有依赖,如多个程序中都调用了printf()函数,则多个程序中都会含有printf.o文件,所有一个目标文件在内存中存在多个副本,浪费空间;更新困难,每当库函数的代码修改了,此时就要重新进行编译汇编链接步骤;但执行快,因为可执行程序中已经包含了所有需要的东西了
b.动态链接:在程序运行时才将各个独立部分链接在一起;例如有两个可执行程序A.o,B.o,都共用一个库lib.o,假设首先A运行,发现其调用lib.o,则会加载lib.o进内存;然后B运行,发现其调用lib.o,此时lib.o由于A的加载已经存在内存了,就无需重新加载,而是将内存中已经存在的lib.o映射到B的虚拟地址空间中,从而进行链接。空间节约以及更新容易,但执行较静态链接稍慢
(二)影响因素
(1)程序的链接方式,如果使用静态链接,执行速度会更快一点,但空间浪费率较大
(2)调度算法的使用
(3)I/O密集型进程是否把大量I/O操作放在主线程执行,是的话会导致CPU大量空余
(4)该程序的局部性是否优秀,例如有无大量使用函数调用或者goto语句
(5)硬件性能:CPU,内存大小,高速缓冲数量,带宽