重写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

相关文章

pycharm远程连接服务器运行pytorch的过程详解

《pycharm远程连接服务器运行pytorch的过程详解》:本文主要介绍在Linux环境下使用Anaconda管理不同版本的Python环境,并通过PyCharm远程连接服务器来运行PyTorc... 目录linux部署pytorch背景介绍Anaconda安装Linux安装pytorch虚拟环境安装cu

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

MySQL 中的服务器配置和状态详解(MySQL Server Configuration and Status)

《MySQL中的服务器配置和状态详解(MySQLServerConfigurationandStatus)》MySQL服务器配置和状态设置包括服务器选项、系统变量和状态变量三个方面,可以通过... 目录mysql 之服务器配置和状态1 MySQL 架构和性能优化1.1 服务器配置和状态1.1.1 服务器选项

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

JavaWeb-WebSocket浏览器服务器双向通信方式

《JavaWeb-WebSocket浏览器服务器双向通信方式》文章介绍了WebSocket协议的工作原理和应用场景,包括与HTTP的对比,接着,详细介绍了如何在Java中使用WebSocket,包括配... 目录一、概述二、入门2.1 POM依赖2.2 编写配置类2.3 编写WebSocket服务2.4 浏

查询SQL Server数据库服务器IP地址的多种有效方法

《查询SQLServer数据库服务器IP地址的多种有效方法》作为数据库管理员或开发人员,了解如何查询SQLServer数据库服务器的IP地址是一项重要技能,本文将介绍几种简单而有效的方法,帮助你轻松... 目录使用T-SQL查询方法1:使用系统函数方法2:使用系统视图使用SQL Server Configu

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.