操作系统
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 条评论
 下一页
  
   
   
  
  
  
  
  
  
  
  
  
  
 