对于一次IO访问(以read举例),数据会先被拷贝到操作系统内核的缓冲区中,然后才会从操作系统内核的缓冲区拷贝到应用程序的地址空间。
当一个read操作发生时,它会经历两个阶段:
因为这两个阶段,Unix系统的IO分为五种模式:
特点就是在IO执行的两个阶段,用户进程都被block了。
Linux中,默认情况下所有的socket都是blocking
特点是用户进程要不断得通过系统调用询问内核,文件描述的数据是否准备好了,这种方式称为轮询(polling)。
如果数据还没有准备好,用户进程不会被阻塞,而是立刻返回一个error。用户进程收到error可以再次进行read操作。
特点是单个用户进程可以处理多个 I/O 事件,减少多进程切换带来的系统开销。
分成三种形式:
select 或者 poll 可以监视多个文件描述符,期间会被阻塞,任何一个描述符的数据准备好后通知用户进程,进程调用 recvfrom 把数据从内核复制到进程中。两者的区别是:
epoll 仅适用于 Linux系统,也可以监视多个文件描述符,内核通过回调函数把数据准备好的文件描述符放入链表,用户进程通过 epoll_wait() 检测到达链表的描述符,不需要轮询所有事件的文件描述符。
epoll又分两种模式:
用户进程执行 aio_read 系统调用会立即返回,可以继续执行,不会被阻塞,内核会在I/O操作完成后向应用进程发送信号。
用户进程使用 sigaction 系统调用后立即返回,可以继续执行,不会被阻塞,内核会在数据准备好后向应用进程发送信号。
用户进程收到信号后调用 recvfrom 将数据从内核复制到应用进程中。
http://cyc2018.gitee.io/cs-notes/#/notes/Socket?id=poll
原文:https://www.cnblogs.com/ChengzhiYang/p/12591675.html