咱们先来看一张Linux
总体架构图。html
系统调用时操做系统的最小功能单位。根据不一样的应用场景,不一样的Linux
发行版本提供的系统调用数量也不尽相同,大体在240-350之间。这些系统调用组成了用户态跟内核态交互的基本接口,例如:用户态想要申请一块20K大小的动态内存,就须要brk系统调用,将数据段指针向下偏移,若是用户态多处申请20K动态内存,同时又释放呢?这个内存的管理就变得很是的复杂。程序员
库函数就是屏蔽这些复杂的底层实现细节,减轻程序员的负担,从而更加关注上层的逻辑实现。它对系统调用进行封装,提供简单的基本接口给用户,这样加强了程序的灵活性,固然对于简单的接口,也能够直接使用系统调用访问资源,例如:open()
,write()
,read()
等等。库函数根据不一样的标准也有不一样的版本,例如:glibc
库,posix
库等。shell
Shell
顾名思义,就是外壳的意思。就好像把内核包裹起来的外壳。它是一种特殊的应用程序,俗称命令行。为了方便用户和系统交互,通常一个Shell
对应一个终端,呈现给用户交互窗口。固然Shell
也是编程的,它有标准的shell
语法,符合其语法的文本叫Shell
脚本。不少人都会用Shell
脚本实现一些经常使用的功能,能够提升工做效率。编程
在CPU
的全部指令中,有一些指令是很是危险的,若是错用,将致使整个系统崩溃。好比:清内存、设置时钟等。若是全部的程序都能使用这些指令,那么你的系统一天死机N回就不足为奇了。因此,CPU
将指令分为特权指令和非特权指令,对于那些危险的指令,只容许操做系统及其相关模块使用,普通的应用程序只能使用那些不会形成灾难的指令。Intel
的CPU
将特权级别分为4个级别:RING0
、RING1
、RING2
、RING3
。安全
当一个任务(进程)执行系统调用而陷入内核代码中执行时,咱们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。微信
当正在执行用户程序而忽然被中断程序中断时,此时用户程序也能够象征性地称为处于进程的内核态。Linux
使用了Ring3
级别运行用户态,Ring0
做为 内核态,没有使用Ring1
和Ring2
。Ring3
状态不能访问Ring0
的地址空间,包括代码和数据。Linux
进程的4GB
地址空间,3G-4G部分你们是共享的,是内核态的地址空间,这里存放在整个内核的代码和全部的内核模块,以及内核所维护的数据。用户运行一个程序,该程序所建立的进程开始是运 行在用户态的,若是要执行文件操做,网络数据发送等操做,必须经过write
,send
等系统调用,这些系统调用会调用内核中的代码来完成操做,这时,必 须切换到Ring0
,而后进入3GB-4GB
中的内核地址空间去执行这些代码完成操做,完成后,切换回Ring3
,回到用户态。网络
这样,用户态的程序就不能 随意操做内核地址空间,具备必定的安全保护做用。架构
处理器总处于如下状态中的一种:函数
一、内核态,运行于进程上下文,内核表明进程运行于内核空间;操作系统
二、内核态,运行于中断上下文,内核表明硬件运行于内核空间;
三、用户态,运行于用户空间。
从用户态到内核态切换能够经过三种方式:
**系统调用:**这是用户态进程主动要求切换到内核态的一种方式,用户态进程经过系统调用申请使用操做系统提供的服务程序完成工做,好比前例中fork()实际上就是执行了一个建立新进程的系统调用。而系统调用的机制其核心仍是使用了操做系统为用户特别开放的一个中断来实现,例如Linux的int 80h中断。
**异常:**当CPU在执行运行在用户态下的程序时,发生了某些事先不可知的异常,这时会触发由当前运行进程切换处处理此异常的内核相关程序中,也就转到了内核态,好比缺页异常。
**外设中断:**当外围设备完成用户请求的操做后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,若是先前执行的指令是用户态下的程序,那么这个转换的过程天然也就发生了由用户态到内核态的切换。好比硬盘读写操做完成,系统会切换到硬盘读写的中断处理程序中执行后续操做等。
这3种方式是系统在运行时由用户态转到内核态的最主要方式,其中系统调用能够认为是用户进程主动发起的,异常和外围设备中断则是被动的。
若是你们喜欢个人文章,能够关注我的订阅号。欢迎随时留言、交流。若是想加入微信群的话一块儿讨论的话,请加管理员简栈文化-小助手(lastpass4u),他会拉大家进群。