手记

【九月打卡】第21天 go的-go的网络层实现

课程名称:深入Go底层原理,重写Redis中间件实战

  

课程章节:8-1,8-2


课程讲师:Moody


课程内容:

※ go的网络层实现

  • 在底层使用操作系统的多路复用IO,比如linux的epoll

  • 在协程层次使用阻塞模型

  • 当协程被阻塞的时候,协程直接休眠,等待被唤醒

※ go里面调用epoll的方法

  • epoll_create() -> netpollinit()

  • epoll_ctl() -> netpollopen()

  • epoll_wait() -> netpoll()

※ netpillinit

  1. 调用系统方法(以linux为例),汇编直接调用epoll_create 创建一个epoll

  2. 新建一个系统的pipe管道用于通知中端Epoll

  3. 将"管道有数据到达"事件注册到Epoll里面

※netpollopen

  1. 传入一个socket的FD和pollDesc指针

  2. pollDesc是go对一个socket的相关信息的抽象

  3. pollDesc还记录了等待socket读写事件的协程

  4. 将Socket可读,可写,断开事件注册到Epoll里面

※netpoll

  1. 调用epoll_wait() 查询那些事件发生了

  2. 根据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描述符上面一样



0人推荐
随时随地看视频
慕课网APP