在 CPU 的全部指令中,有些指令是很是危险的,若是错用,将致使系统崩溃,好比清内存、设置时钟等。若是容许全部的程序均可以使用这些指令,那么系统崩溃的几率将大大增长。因此,CPU 将指令分为特权指令和非特权指令,对于那些危险的指令,只容许操做系统及其相关模块使用,普通应用程序只能使用那些不会形成灾难的指令。linux
当进程运行在内核空间时就处于内核态,而进程运行在用户空间时则处于用户态。windows
在内核态下,进程运行在内核地址空间中,此时 CPU 能够执行任何指令。运行的代码也不受任何的限制,能够自由地访问任何有效地址,也能够直接进行端口的访问。
在用户态下,进程运行在用户地址空间中,被执行的代码要受到 CPU 的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中 I/O 许可位图(I/O Permission Bitmap)中规定的可访问端口进行直接访问。服务器
对于 Linux 来讲,经过区份内核空间和用户空间的设计,隔离了操做系统代码(操做系统的代码要比应用程序的代码健壮不少)与应用程序代码。即使是单个应用程序出现错误也不会影响到操做系统的稳定性,这样其它的程序还能够正常的运行(Linux 但是个多任务系统啊!)。网络
因此,区份内核空间和用户空间本质上是要提升操做系统的稳定性及可用性。并发
每一个处理器在任何指定时间点上的活动归纳为下列三者之一:框架
以上三点几乎包括全部的状况,好比当 CPU 空闲时,内核就运行一个空进程,处于进程上下文,但运行在内核空间。异步
一些对外围设备的访问操做好比硬盘、网卡都只能运行在内核态,此外进程调度、TCP/IP协议栈等也只能工做在内核态。socket
文件描述符是一个非负整数,实际上,他是一个索引值,指向内核为每个进程所维护的该进程打开文件的记录表,当程序打开一个现有文件或者建立一个新文件时,内核向进程返回一个文件描述符。当咱们的进程想要对文件进行读写的时候,就会传递这个文件描述符给内核空间,内核就会根据不一样类型的IO对相应的数据进行操做返回。 用户进程若是想要从外围设备(这里以socket为例)读取数据,须要首先通过内核,那这里就涉及到和内核的通讯问题了。
高并发
好比说网络io,当咱们须要去获取一个网页的数据返回的时候,若是服务器无返回的时候,就会一直阻塞等待数据返回。这样cpu的浪费就很严重。编码
用户进程想要读取数据了,因而就经过执行recvfrom来进行一次系统调用,进入内核态,内核态若是数据没有准备好就直接返回一个没有准备好的标志,咱们这边的用户进程也没有闲着,就去干别的事了,(可是后面的执行须要用到数据的话,那么仍是要等待数据返回)可是仍是会定时轮询系统调用查看数据是否准备好
前面的前面两种方式一个进程只能监听一个返回状态,但select能够同时监听多个返回状态,好比同时发起100个socket,一旦有一个数据返回了就去当即处理。因此说效率大大提升了。可是将数据从内核复制到用户控件这个时间仍是有浪费。
获得数据以后,操做系统会将数据从内核复制到用户空间以后,再给信号处理程序发起数据。少了中间拷贝数据的过程,是操做系统准备好了以后再发给用户进程的。异步io在io复用的基础上没有太大的提高, 可是编码难度复杂,因此现在不少程序的框架仍是普遍使用的仍是io复用。
分析:epoll不必定就比select好,