5分钟搞懂用户态,内核态
1. 什么是用户态,内核态
用户态就是提供应用程序运行的空间,为了使应用程序访问到内核管理的资源例如CPU,内存,I/O。内核必须提供一组通用的访问接口,这些接口就叫系统调用。
用户态,内核态是指程序所处的状态。我们写的一段程序,我们所写的这段程序在运行过程中,有可能处于用户态,也有可能处于内核态。可能在某一个时刻处于用户态,下一个时刻切换到内核态。
那么用户态在什么时候可以切换到内核态呢?是在满足什么条件的时候触发的呢?
那么这个触发条件就是我们的程序需要去申请外部资源的时候。那么外部资源到底指的是什么呢?比如说内存条,显卡,磁盘,声卡,网卡,usb, 主板上的外设,主板上的LED,都属于外部资源。
也就是当需要操作这些硬件的时候,都需要从用户态转为内核态。
2. 用户态切换到内核态的方式
-
系统调用,这个上面已经讲解过了,在我公众号之前的文章也有讲解过。其实系统调用本身就是中断,但是软件中断,跟硬中断不同。
-
异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,就会触发切换。例如:缺页异常。
-
外设中断:当外设完成用户的请求时,会向CPU发送中断信号。
3. 系统调用
重点说一下系统调用,因为最常用的就是系统调用。 通过 man syscalls 可以获取所有的系统调用。包括5大类。
-
进程控制相关的, process control。指令:exit, fork
-
文件管理相关的, file system control。指令:chmod,chown,open
-
设备相关的, device control。指令:read,write
-
信息相关的,比如说要获取 cpu相关的信息等。指令:getcpu
-
通信相关的。比如说进程间的通信等。比如说管道就是一个系统调用。指令:pipe, mmap。
4. 内核态切换到用户态
就是当内核态的任务执行完毕的时候,就回切换为用户态。
5. 举几个例子
-
例如读写文件的时候,就会触发用户态到内核态的转换。这个时候会进行一个系统调用,(open/read/write)
-
申请内存。这里的内存指的是堆内存。c 语言中会调用 malloc 这个函数,但是并没有一个系统调用是 malloc。malloc 中会分为俩种系统调用,第一个是 brk. 第二种是通过 mmap. 在小于 128k 内存申请的时候会调用brk。brk 和 mmap 申请的是虚拟地址空间。它并没有申请到主存上的真正的物理内存空间。想要申请到真正的物理内存,那么就需要在第一次访问的时候,如果发现虚拟内存地址没有映射到物理内存地址,那么就会触发一个缺页中断。
总结
本篇文章,没有非常深入的Linux内核实现,只是从宏观的角度阐述了下。看完上面的文章,也能得出一点结论就是:系统调用真的开销蛮大的。涉及到上下文的切换。
鸣谢
搞懂用户态,内核态