个人Github地址 github.com/AmbitionTn/… , 希望下面的文章对大家有所帮助,要是觉得感兴趣可以关注一下,会持续更新,持续学习中
读书记录:LINUX是怎样工作的
计算机系统硬件结构
在计算机系统运行时,在硬件设备上会重复以下步骤
- 通过输入输出设备或网络适配器,向计算机发送请求。
- 读取内存中命令,并在CPU上执行,把结果写入负责保存数据的内存区域中
- 将内存中的数据写入HDD,SDD等
- 重复步骤1
进程是如何与设备交互的
-
CPU存在内核模式与用户模式两种模式,LINUX为了减少开发人员对于设备的调用都要写重复的调用的逻辑,提供了设备驱动器,所有的设备的交互都是通过设备驱动器做的,同时为了避免进程直接调用设备,对于设备的调用必须是内核模式做的。
-
用户模式与内核模式交互是通过系统调用完成的。
进程与OS的关系
一般来说,用用户模式下运行的进程通过系统调用向内核发送相应的请求,其中存在进程独有的代码、三方库,也存在OS提供的库。
系统调用
进程在执行创建进程、操控硬件等依赖于内核处理时,必须通过系统调用向内核发送请求。系统调用的种类如下
- 进程控制(创建和删除)
- 内存管理(分配和释放)
- 进程间通信
- 网络管理
- 文件系统操作
- 文件操作(访问设备)
CPU的模式切换
系统调用通过执行特殊的CPU命令来发起。通常进程运行在用户模式下,当通过系统调用向内核发送请求时,CPU会发生名为中断的事件。这时,CPU将从用户模式切换到内核模式,然后根据请求内容进行相应的处理。当内核完成系统调用户,会重新回到用户模式,继续运行进程。
内核在开始的处理时验证来自进程的请求是否合理(例如请求内存量是否大于系统所需的内存量)。如果请求不合理,系统调用将会执行失败。
并不存在用户进程绕过系统调用而直接切换CPU运行模式的方法
实验
strace命令
下面使用Go程序编写Hello world 来看一下系统调用的场景
package main
import "fmt"
func main() {
fmt.Println("Hello world")
}
使用strace查看系统调用情况,strace -o 输出到文件
strace -o hello.log ./hello
可以关注一下箭头这里,发生系统调用,调用Write打印到屏幕上。
sar命令
sar命令用于获取进程分别在用户模式与内核模式下运行的时间比例。
sar -P ALL 1 3
- 可以写一个循环程序,看一下CPU用户模式和内核模式的时间占比,以及写一个循环系统调用,看下占比情况。
总结
通过理解计算机结构以及进程是如何与内核交互的。当在进程中我们写一个循环、写一个系统调用、或是一个打印字符串的语句,到底经历了哪些步骤才完成交互的。通过这个过程的理解,对于后续的程序开发能够更加清楚运行情况,做到更多的思考和优化。
下面是这篇文章的一些和核心点:
- 进程与内核交互必须通过系统调用发送中断信号才可以,不能够直接切换CPU模式
- 对于设备操作、文件操作、进程控制、网络管理等都是内核模式处理的。
- 用户模式不能直接操作内核