begin
用户态&内核态
内核态:内核本质是一种软件,控制计算机的硬件资源,并提供上层环境
用户态: 上层应用程序活动空间,应用程序的执行要依赖于内核提供的资源,(包括cpu资源,存储资源,io资源)
用户态的程序要访问内核态的资源可以通过:系统调用
系统调用通过库函数及shell脚本进行封装,屏蔽复杂的底层实现细节,对系统调用进行封装,提供简单的接口给用户
从用户态到内核态除了系统调用还有其他方式进入吗?共有三种方式
1.系统调用:相对于外设中断则属于软中断(主动请求切换)
2.异常(缺页异常,被动切换)
3.外设中断,当外设完成用户请求时,会向cpu发送中断信号,此时cpu会暂停并执行下一条即将执行的指令,转而去执行中断信号对应的处理程序
五种网络io模型:
阻塞IO(bloking IO):
应用进程调用recvform,执行系统调用,直到有数据报被拷贝到应用进程才返回,否则进程一直处于阻塞状态。此时会把cpu给交出去不会一直占用
https://blog.csdn.net/qq_35462323/article/details/94565766(理解整理为什么不会阻塞)
工作队列 > 等待队列 > 唤醒进程
当进程调用recvfrom时候会进行阻塞,os会创建一个由文件系统管理的socket的对象,此对象保函发送缓冲区./ 接收缓冲区/等待队列。。此时调用recv的进程会被移动到该socket的缓冲队列中,然后cpu的执行队列中没有了该进程,所以该进程虽然被阻塞了(被socket对象阻塞了),但是没有占用cpu,不影响cpu的执行
非阻塞IO(non-blocking IO):
用轮询的方式一直请求内核看数据有没有拷贝完,所以非阻塞io不会释放cpu会一直轮询,造成cpu浪费
多路复用IO(multiplexing IO):
概念一(多路分离函数select):可以解决非阻塞io的轮询问题,工作方式:通过内核提供的多路分离函数select;用户先将需要io操作的socket添加到select上,然后阻塞等待select系统调用返回,当数据到达时候,socket被激活,select函数返回,用户发起read请求,读取数据;优势在于用户在一个线程中可以注册多个socket,不断的调用select读取被激活的socket,达到一个线程处理多个io的请求
因为这样每个io请求还是阻塞的,阻塞在select函数上,为了达到能让用户进程不阻塞去处理其他事情引出概念二
概念二(Reactor /io多路复用):用户线程注册到Reactor上,然后reactor负责调用内核的select函数检查socket,当有socket被激活后通知其对应的用户线程(回调),所以这样情况下用户线程不会被阻塞,因为用户线程要处理io的时候,数据已经到达了
优点:单个线程可以处理多个网络接连io,原理在于不再又应用程序监听链接,而是由内核替代应用程序监听文件描述符;
例如:
1.用户调用select,整个进程会阻塞,2.内核会监听select负责的socket,当有一个socket的数准备好,select就会返回,3.然后用户在进行read操作,将数据从内核到用户区
问题:此方式应用程序会有两个调用一个是select 一个是 recvfrom;所以在连接数不多的情况下不如bio的模式知会调用一个recvfrom;反正也是会阻塞,优点就在于一个连接可以处理多个connection;
io多路复用中的select poll epoll函数介绍:这些机制主要做的是一个任务是监听多个描述符,一旦某个描述符就绪,就通知对应的程序进行对应的读写操作;但是收到通知以后还是线程自己去内核进行读取,而异步io实现会把数据从内核考到用户空间
select:
监视三类文件描述符:writefds;readfds;exceptsfds;调用select函数会阻塞;直到有描述符就绪;超时;当select韩式返回时可以通过遍历fdset;找到已经就绪的描述符
缺点:能够监听的最大描述符是1024个
poll:
与select不同的在没有最大数量的限制,但是数量过大后也会下降,与select一样,poll返回后,需要轮询pollfd来获取就绪的描述符
注:select和poll都需要返回后,遍历文件描述符来获取已经就绪的socket。事实上同一时刻就绪的socket会很少,所以随着监听的描述符数量的增加,其效率会线性下降
epoll:
使用一个文件描述符管理多个描述符
epoll_creat():告诉内核监听的数目有多大,不是限制只是内核初始分配的建议,但是内核会占用这些描述符,所以使用完了,必须要关闭掉。
epoll_ctl(): epfd : epoll_creat的返回值 ;op:三个宏来表示:添加,删除,修改
fd:要监听的fd(文件描述符);epoll_event:告诉内核需要监听什么事
epoll_wait():等待epfd上的io事件,最多返回maxevents个事件;
events参数是内核回来的事件之和,maxevents表明内核返回了多少数据 <= epoll_creat(int size),int timeout 超时时间,此方法返回数据是处理的事件数量
使用了Reactor模型 >>>传送>>>>>文章正在审核中... - 简书
信号驱动式IO(signal-driven IO):
应用程序使用套接字进行信号驱动I/O,通过sigaction系统调用安装一个信号处理函数,用户进程运行不阻塞,当数据准备好以后,内核会发出一个sigio信号给信号处理函数,信号处理函数调用io操作处理数据。
缺点:信号IO在有大量的io操作的时候,会因为信号队列的溢出导致没法通知
异步IO(asynchronous IO):
io多路复用是将文件的句柄的状态通知给用户线程,由用户自行读取数据处理数据,异步io是数据内核已经处理完了,并且放在用户线程的指定的缓冲区域了,当用户线程得到通知后可以直接使用数据;
使用了Proactor模型模型 >>>传送>>>>>文章正在审核中... - 简书