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

2024-02-04 15:36

本文主要是介绍重写Sylar基于协程的服务器(6、HOOK模块的设计),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

重写Sylar基于协程的服务器系列:

重写Sylar基于协程的服务器(0、搭建开发环境以及项目框架 || 下载编译简化版Sylar)

重写Sylar基于协程的服务器(1、日志模块的架构)

重写Sylar基于协程的服务器(2、配置模块的设计)

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

重写Sylar基于协程的服务器(4、协程调度模块的设计)

重写Sylar基于协程的服务器(5、IO协程调度模块的设计)

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

简述

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


本章完结

这篇关于重写Sylar基于协程的服务器(6、HOOK模块的设计)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/677981

相关文章

Python极速搭建局域网文件共享服务器完整指南

《Python极速搭建局域网文件共享服务器完整指南》在办公室或家庭局域网中快速共享文件时,许多人会选择第三方工具或云存储服务,但这些方案往往存在隐私泄露风险或需要复杂配置,下面我们就来看看如何使用Py... 目录一、android基础版:HTTP文件共享的魔法命令1. 一行代码启动HTTP服务器2. 关键参

Mysql中设计数据表的过程解析

《Mysql中设计数据表的过程解析》数据库约束通过NOTNULL、UNIQUE、DEFAULT、主键和外键等规则保障数据完整性,自动校验数据,减少人工错误,提升数据一致性和业务逻辑严谨性,本文介绍My... 目录1.引言2.NOT NULL——制定某列不可以存储NULL值2.UNIQUE——保证某一列的每一

SpringBoot改造MCP服务器的详细说明(StreamableHTTP 类型)

《SpringBoot改造MCP服务器的详细说明(StreamableHTTP类型)》本文介绍了SpringBoot如何实现MCPStreamableHTTP服务器,并且使用CherryStudio... 目录SpringBoot改造MCP服务器(StreamableHTTP)1 项目说明2 使用说明2.1

JAVA覆盖和重写的区别及说明

《JAVA覆盖和重写的区别及说明》非静态方法的覆盖即重写,具有多态性;静态方法无法被覆盖,但可被重写(仅通过类名调用),二者区别在于绑定时机与引用类型关联性... 目录Java覆盖和重写的区别经常听到两种话认真读完上面两份代码JAVA覆盖和重写的区别经常听到两种话1.覆盖=重写。2.静态方法可andro

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

mysql中的服务器架构详解

《mysql中的服务器架构详解》:本文主要介绍mysql中的服务器架构,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、mysql服务器架构解释3、总结1、背景简单理解一下mysqphpl的服务器架构。2、mysjsql服务器架构解释mysql的架

Linux如何快速检查服务器的硬件配置和性能指标

《Linux如何快速检查服务器的硬件配置和性能指标》在运维和开发工作中,我们经常需要快速检查Linux服务器的硬件配置和性能指标,本文将以CentOS为例,介绍如何通过命令行快速获取这些关键信息,... 目录引言一、查询CPU核心数编程(几C?)1. 使用 nproc(最简单)2. 使用 lscpu(详细信

Nginx 重写与重定向配置方法

《Nginx重写与重定向配置方法》Nginx重写与重定向区别:重写修改路径(客户端无感知),重定向跳转新URL(客户端感知),try_files检查文件/目录存在性,return301直接返回永久重... 目录一.try_files指令二.return指令三.rewrite指令区分重写与重定向重写: 请求

MySQL MCP 服务器安装配置最佳实践

《MySQLMCP服务器安装配置最佳实践》本文介绍MySQLMCP服务器的安装配置方法,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下... 目录mysql MCP 服务器安装配置指南简介功能特点安装方法数据库配置使用MCP Inspector进行调试开发指