操作系统
2021-04-12 17:19:26 1 举报
AI智能生成
操作系统IO\线程相关学习笔记
作者其他创作
大纲/内容
IO分类
缓冲IO
对应C语言库常见函数
内存示意
直接IO
对应Linux系统Api
内存示意
特别说明
fflush和fsync区别
直接io read/write和 pread和pwrite区别
内存概念
应用程序内存
用户缓存区
内核缓冲区
内存映射和零拷贝
内存映射
比直接IO更近一步,数据拷贝次数只有1次,linux系统中内存映射文件对于的系统API是 void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset), Java 中 MappedByteBuffer类实现同样的目的
零拷贝
场景 用户把文件数据发送到网络
直接IO 实现逻辑 内存拷贝2次 ,数据拷贝4次
内存映射实现 内存copy 1次 数据考虑3次
零拷贝 数据在内存拷贝0次 数据拷贝2次
Linux 零拷贝系统API sendfile( int out_fd,int in_fd,off_t *offset,size_t count)
Java 对应 FileChannel.transferTo(long position,long count,WriteByteChannel target)
网络IO模型(LInux系统)
同步阻塞IO
linux read和write函数,调用时阻塞,直到数据读取完成或写入成功
同步非阻塞IO
和同步阻塞IO的API一样,打开fd时带有O_NONBLOCK参数,如果数据没有准备好,直接返回不阻塞,需要应用系统不断轮询
IO多路复用
三种方法 select \poll \ epoll
select linux api(int maxfdps,fd_set *readfds, fd_set *writefds,fd_set *exceptfds..)
fd是一个int值,所以fd_set其实是一个bit数组,每一位标识一个fd是否有读事件或写事件发生
第一个参数是readfds或writefds下标最大值+1,因为fd从0开始,+1才表示这个数
返回结果还在readfds和writefds里,操作系统会重置所有bit位,告知应用那个fd上有事件,应用程序需要自己遍历0到maxfds-1,然后执行read或write操作
每次select调用用,在下次调用前要重新维护readfds和writefds
poll
int poll (struct pollfd * fds, unsigned int nfds,int timeout); struct pollfd { int fd;short events; short revents; }
和select 一样,需要将fd数据传进度,每次fd数组在用户和内核态传递,影响效率
epoll linux系统中性能最好的多路复用模型
epoll 传递epfd,是一个数字,把fd数组关联到尚敏每次向内核传递的是epfd这个数字
三个步骤 事件注册 轮询事件是否就绪 执行IO操作
事件注册 accept read write
轮询事件是否就绪
执行IO操作
异步IO 读写由操作系统完成
windows的IOCP
asio 是一个上层架构层的“异步IO”,或者模拟处理的异步IO,底层在Linux系统上还是使用epoll实现,在这里“异步”,就是读写由底层框架或系统完成,完成以后,通知应用程序
linux aio,但是不太成熟
网络IO模型对比
Reactor和Proactor模式
Reactor 模式 主动模式。应用系统不断轮询操作系统或框架、IO是否就绪。linux系统的select、poll、epoll,Java中的NIO 都属于这种模式
Proactor 模式 被动模式。 应用程序把read和write函数操作全部交给操作系统,实际IO由操作系统或框架完成,之后再回调应用。asio库就是Proactor模式
select、epoll的LT和ET
LT(水平触发)模式
读缓冲区只要不为空,一直触发读事件;写缓冲区不满,一直触发写事件;
LT模式下避免写的死循环,一般写满的概率小,如果无数据可写,要取消写事件。
Java NIO用的是epoll的LT模式
ET(边缘触发\状态触发)模式
读缓冲区状态从空转为非空触发一次;写缓冲区从满到非满触发一次;
ET模式要避免short read。用户收到100字节,只读取了50字节,剩下50字节也不会再触发事件,一定要不读缓冲区数据一次性读完。容易漏事件,一次触发没有处理好,就没有第二次机会了
服务器编程的1+N+M模型
进程、线程和协程
多线程
优点:提供CPU利用率;提供IO吞吐
缺点:线程同步机制复杂(常见的锁、wait与signal、Condition)
多进程
优点:进程间一般不共享内存;减少了再不同CPU之间切换的开销;多进程相互独立,不影响
典型例子:nginx 多进程 单线程
协程
优点:更好利用cpu,应用程序可以自己调度;更好利用内存,协程堆栈大小不固定,用多少申请多少;
GO、Rust原生支持,Java第三方Quasar Fiber,C++的libco
无锁(内存屏障与CAS)
内存屏障
将cpu缓存值刷到内存中
防止指令重排
java 中的volatile关键字有以上两个能力
CAS
CPU提供的硬件原子指令,使用Compare And Set 两个操作的原子化
ABA问题
0 条评论
下一页