当前位置: 首页 > news >正文

重写Sylar基于协程的服务器(6、HOOK模块的设计)

重写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流程如下。

  1. 进入do_io函数内部,首先会检查socketfd的合法性。

  2. 如果socketfd是合法的,就去调用fun。(fun是通过do_io参数传进来的真正的io系统调用函数地址)。

  3. 如果sockefd是非法的,也会去调用一次fun,fun返回什么,do_io就返回什么,完全依赖原始的系统底层调用对非法socketfd的处理。

  4. 对于合法的socketfd调用fun,由于socketfd是非阻塞的,不管是否读取到数据,fun都会立刻返回。如果读到数据,do_io整体就返回读到的字节数。如果没有读到数据,fun会返回-1,errno为EAGAIN,但是do_io不会返回。

  5. 然后调用线程当前的IOManager的addEvent函数,根据用户调用的socketIO相关接口对socketfd添加事件相应读写事件,在addEvent函数内部会把<当前协程,当前协程的协程调度器>放入socketfd对应的EventContext结构体里面,等待socketfd上io事件到来并由idle协程调用TrigleEvent函数唤醒当前协程。

  6. 然后调用yieldToHold将协程变成Hold状态,等待socketfd上io事件到来时idle协程将该协程唤醒。

  7. 唤醒后,首先查看是怎么被唤醒的,如果是因为超时被唤醒,do_io就返回超时的错误,如果是因为有io事件到来被唤醒,那么回到第4步。

HOOK模块核心函数do_io伪代码:

do_io伪代码

do_io的使用(也即read、write系统调用的hook)

read、write的hook

下一章将介绍TcpServer模块。

感兴趣的同学,可以阅读一下本文实现的源码:https://github.com/LunarStore/lunar


本章完结

相关文章:

  • MongoDB 聚合:$listSessions
  • Java 正则匹配sql
  • C#验证字符串的长度,用正则表达式 vs 字符数组长度或字符串的长度
  • 字符函数和字符串函数
  • 数据结构——B/顺序表和链表
  • 自动化报告pptx-python|如何将pandas的表格写入PPTX(二)
  • MAE实战:使用MAE提高主干网络的精度(一)
  • 回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)
  • Linux项目自动化构建工具之make/Makefile演示gcc编译
  • [MFC] MFC消息机制的补充
  • 网络安全-端口扫描和服务识别的几种方式
  • 2.3作业
  • QT 范例阅读:系统托盘 The System Tray Icon example
  • React useEffect使用
  • eCos flash模拟EEPROM实现NV系统
  • 分享的文章《人生如棋》
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • 03Go 类型总结
  • Android组件 - 收藏集 - 掘金
  • CentOS从零开始部署Nodejs项目
  • create-react-app做的留言板
  • JAVA_NIO系列——Channel和Buffer详解
  • JavaScript DOM 10 - 滚动
  • select2 取值 遍历 设置默认值
  • Solarized Scheme
  • 安卓应用性能调试和优化经验分享
  • 彻底搞懂浏览器Event-loop
  • 程序员最讨厌的9句话,你可有补充?
  • 从零搭建Koa2 Server
  • 经典排序算法及其 Java 实现
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 深入浅出Node.js
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 容器镜像
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • #pragma预处理命令
  • #QT项目实战(天气预报)
  • (1)(1.13) SiK无线电高级配置(五)
  • (附源码)计算机毕业设计ssm电影分享网站
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .NET CORE Aws S3 使用
  • .NET Project Open Day(2011.11.13)
  • .NET Remoting学习笔记(三)信道
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • .net通用权限框架B/S (三)--MODEL层(2)
  • /run/containerd/containerd.sock connect: connection refused
  • [CISCN 2023 初赛]go_session
  • [CQOI 2011]动态逆序对
  • [C和指针].(美)Kenneth.A.Reek(ED2000.COM)pdf
  • [C语言]——内存函数
  • [hadoop读书笔记] 第十五章 sqoop1.4.6小实验 - 将mysq数据导入HBASE