精通网站开发,网站建设的财务分析,wordpress 无法访问,小学网站怎么做重写Sylar基于协程的服务器#xff08;6、HOOK模块的设计#xff09;
重写Sylar基于协程的服务器系列#xff1a; 重写Sylar基于协程的服务器#xff08;0、搭建开发环境以及项目框架 || 下载编译简化版Sylar#xff09; 重写Sylar基于协程的服务器#xff08;1、日志模…重写Sylar基于协程的服务器6、HOOK模块的设计
重写Sylar基于协程的服务器系列 重写Sylar基于协程的服务器0、搭建开发环境以及项目框架 || 下载编译简化版Sylar 重写Sylar基于协程的服务器1、日志模块的架构
重写Sylar基于协程的服务器2、配置模块的设计
重写Sylar基于协程的服务器3、协程模块的设计
重写Sylar基于协程的服务器4、协程调度模块的设计
重写Sylar基于协程的服务器5、IO协程调度模块的设计
重写Sylar基于协程的服务器6、HOOK模块的设计
重写Sylar基于协程的服务器7、TcpServer HttpServer的设计与实现
简述
HOOK模块存在的必要性让IO系统调用以同步写法展现出异步的性能。
hook实际上就是对系统调用API进行一次封装将其封装成一个与原始的系统调用API同名的接口应用在调用这个接口时会先执行封装中的操作再执行原始的系统调用API。本文实现的是一种利用dlsym函数实现的侵入式hook。
HOOK的实现
首先是hook重新实现accept函数、socket函数为了高效的cpu利用率每个被accept函数接受的socketfd、或者socket创建的fd在返回给调用者前都会使用fcntl函数将其设置为非阻塞虽然socketfd被设置成非阻塞的但是我们的hook机制能够利用非阻塞的socketfd实现一种在调用者看来是阻塞的socketfd。
其次为了获取socketfd的超时时间所有setsockop也会被hook如果socketfd之前使用setsockop函数设置超时其超时时间就会被fdmanager类获取将超时时间记录在对应的fd上。当然为了善后close也会被hook在调用真正close前会唤醒相应socketfd上的所有监听协程让协程退出。
最后将socketIO有关的系统调用如read、write、accept等抽象出一个统一的接口do_io用户在调用socketIO有关函数时底层统一调用do_io。do_io流程如下。 进入do_io函数内部首先会检查socketfd的合法性。 如果socketfd是合法的就去调用fun。fun是通过do_io参数传进来的真正的io系统调用函数地址。 如果sockefd是非法的也会去调用一次funfun返回什么do_io就返回什么完全依赖原始的系统底层调用对非法socketfd的处理。 对于合法的socketfd调用fun由于socketfd是非阻塞的不管是否读取到数据fun都会立刻返回。如果读到数据do_io整体就返回读到的字节数。如果没有读到数据fun会返回-1errno为EAGAIN但是do_io不会返回。 然后调用线程当前的IOManager的addEvent函数根据用户调用的socketIO相关接口对socketfd添加事件相应读写事件在addEvent函数内部会把当前协程当前协程的协程调度器放入socketfd对应的EventContext结构体里面等待socketfd上io事件到来并由idle协程调用TrigleEvent函数唤醒当前协程。 然后调用yieldToHold将协程变成Hold状态等待socketfd上io事件到来时idle协程将该协程唤醒。 唤醒后首先查看是怎么被唤醒的如果是因为超时被唤醒do_io就返回超时的错误如果是因为有io事件到来被唤醒那么回到第4步。
HOOK模块核心函数do_io伪代码 do_io的使用也即read、write系统调用的hook 下一章将介绍TcpServer模块。
感兴趣的同学可以阅读一下本文实现的源码https://github.com/LunarStore/lunar 本章完结