课程章节:8-1,8-2
课程讲师:Moody
课程内容:
※ go的网络层实现
在底层使用操作系统的多路复用IO,比如linux的epoll
在协程层次使用阻塞模型
当协程被阻塞的时候,协程直接休眠,等待被唤醒
※ go里面调用epoll的方法
epoll_create() -> netpollinit()
epoll_ctl() -> netpollopen()
epoll_wait() -> netpoll()
※ netpillinit
调用系统方法(以linux为例),汇编直接调用epoll_create 创建一个epoll
新建一个系统的pipe管道用于通知中端Epoll
将"管道有数据到达"事件注册到Epoll里面
※netpollopen
传入一个socket的FD和pollDesc指针
pollDesc是go对一个socket的相关信息的抽象
pollDesc还记录了等待socket读写事件的协程
将Socket可读,可写,断开事件注册到Epoll里面
※netpoll
调用epoll_wait() 查询那些事件发生了
根据Socket相关的pollDesc信息,返回那些协程可以唤醒,因为这些协程是关心event的
※补充:
go的用户层看来,协程虽然是阻塞I/O模型,Socket是阻塞的,因为抽象了Socket的pollDesc是阻塞的。但是实际上,这是go的netpoller通过I/O多路复用机制模拟出来的,对应的底层操作系统Socket实际上是非阻塞的,只是在运行时,拦截了针对底层Socket的系统调用返回的错误码,并通过netpoll而和 协程调度让协程阻塞在用户层所看到的Socket描述符上。 比如:当用户层针对某一个socket描述符发起read操作的时候,如果该socket上尚无可读数据,那么go运行时会将该socket加入到netpoller中监听,直到go收到该socket数据可读的通知,也就是事件。接着,go才会唤醒关心这个sokcet 的read事件的协程。这个过程,从协程的视角来看,就像read事件一直阻塞在Socket描述符上面一样
共同学习,写下你的评论
评论加载中...
作者其他优质文章