首页 > 其他分享 >muduo学习笔记

muduo学习笔记

时间:2023-06-09 11:55:22浏览次数:26  
标签:muduo Reactor epoll 阻塞 笔记 学习 调用 IO loop

目录

概念

阻塞和非阻塞

\(\bf{ 网络 \rm{IO} 阶段一:}\\ 数据准备 \begin{cases} 阻塞:\quad调用 \rm{IO} 方法线程进入阻塞状态 \quad \\ \\非阻塞:\quad不会改变线程状态,通过返回值判断(需要将sockfd设置为非阻塞状态)\end{cases}\)

ssize_t  recv(int sockfd,void *buf,size_t : len,int : flag);

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程


同步和异步

\(\bf{网络\rm{IO}阶段二:}\\ 数据读写 \begin{cases} 同步:(订票→等待出票→拿票) \\ \\ 异步:(订票→干自己的事→出票(机场通知拿票))\end{cases}\)

同步:

需要自己将数据放到缓冲区

char buf[1024]={0};
int size =  recv(sockfd, buf, 1024, 0);
if( size>0 ){
    ...
}

异步:

应用程序自己往下执行,由操作系统将数据放入缓冲区并发出通知。
预先设置通知方式,操作系统提供异步IO接口。 Linux下(aio_read,aio_write)

同步和异步的区别:请求发出后,是否需要等待结果,才能继续执行其他操作。

总的来说,同步和异步关注的是任务完成消息通知的机制,而阻塞和非阻塞关注的是等待任务完成时请求者的状态。

Unix/Linux上的5种IO模型

典型的一次IO两个阶段:数据就绪和数据读写

阻塞 Blocking


进程阻塞于read

非阻塞 non-blocking


进程调用read,判断EAGAIN反复调用

IO复用 IO multiplexing


进程阻塞于select/poll/epoll等待套接字变为可读,阻塞于read读数据

信号驱动 signal-driven


进程继续执行,阻塞于read读数据。于非阻塞IO的区别在于提供了消息通知机制,无需用于进程轮询查询

异步 asynchronous

典型异步非阻塞状态,Node.js采用的IO模型

网络服务器设计

Reactor模型

sequenceDiagram participant Event participant Reactor participant Demultiplex participant EventHandler Event ->> Reactor:注册Event和Handler loop 事件集合 Reactor -> Reactor:Event集合 end Reactor ->>Demultiplex:向Epoll add/mod/del Event Reactor ->>Demultiplex:启动反应堆 loop 事件发生器 Demultiplex ->Demultiplex:开启事件循环epoll_wait end Demultiplex ->> Reactor:返回发生事件的Event Reactor ->> EventHandler:调用Event事件对应的事件处理器EventHandler

reactor主要存储了事件和事件对应的处理器

epoll

select和poll的缺点

select的缺点:

  1. 能监视的最大文件描述符存在限制(1024),而且由于是轮询的方式,一旦监视的文件描述符增多,性能越差
  2. 内核于用户空间的内存拷贝问题,产生大量开销
  3. select返回整个句柄数据,应用程序需要便利整个数组才能知道那个句柄发生事件
  4. 水平触发模式,如果没有完成一个已经就绪的文件描述符进行IO,那么下次select还是会通知这个描述

select相比,poll采用的是链表存储文件描述符,除了第一点其余三个缺点均存在。


epoll的原理和优势

与poll/select机制完全不同,epollLinux内核申请一个简易的文件系统,IO效率高

主要分成3个流程

  • 调用epoll_create()建立一个epoll对象
  • 调用epoll_ctlepoll对象中
  • 调用epoll_wait收集发生事件的sockfd

触发模式

LT模式

epoll默认的模式

数据没有读完就会一直上报

ET模式

数据只会上报一次

muduo采用的是LT模式

大概原因:

  • 不丢失数据

    • 没有读完,内核会不断上报
  • 低延时处理

    • 每次读数据只需要一次系统调用,照顾了连接的公平性
  • 跨平台

    • select一样可以跨平台使用

关键组件

noncpoyable

很多类都继承了这个类,是为了让类无法拷贝构造和赋值

class noncopyable{
    public:
    noncopyable(const noncopyable& )=delete;
    noncopyable& operator=(const noncopyable&)=delete;
    protected:
    noncopyable()=default;
    ~noncopyable()=default;
}

Channel

封装了fdeventsrevents以及一组回调

  • fd:往poller上注册的文件描述符
  • events:事先关注的事件
  • revent:文件描述符所返回的事件,根据相应的事件触发相应的回调。

分为两种channel,一个是用于listenFd用于接收连接,一种是connFd是已建立连接的客户端,其中listenFd封装为acceptorChannelconnFd封装为connectionChannel


Poller和EPollPoller - Demultiplex

poller中记录了一个表unorder_map<int,channel*>,如果有事件发生,就找到对应的channel,其中就记录了详细的事件回调


EventLoop - Reactor

保存了一系列的Channel,即ChannelList,存储了活跃的Channel
还有非常重要的weakFdstd::unique_ptr<Channel> wakeUpChannel,一个weakupFd隶属于一个loop,二者一一对应,驱动loop是通过往weakupFd中写入数据,weakupfd也封装成了Channel注册在了EPollPoller


Thread和EventLoopThread


EventLoopThreadPool

getNextLoop():通过轮询算法获取下一个subloop
一个Thread对应一个loop=> one loop peer thread


Acceptor

主要封装了listenFd相关的操作,包括socket bind listen,然后扔给baseloop


Buffer

缓冲区,应用写数据->写入缓冲区->Tcp发送缓冲区->send

	+------------------+-------------------+---------------+
 	| 	preable bytes  |  readable bytes   |	writable   |
 	+------------------+-------------------+---------------+
 	|				   |				   |			   |
 	0				readIndex			writeIndex		  size


TcpConnection

一个成功连接的客户端对应一个TcpConnection
封装了socket channel callback,发送、接收缓冲区


TcpServer

封装了Acceptor EventLoopThreadPool和一堆callback
connectionMap connection_,记录所有的连接

初始化流程

  1. 构建TcpServer对象,在TcpServer构造函数中:Acceptor->setNewConnectionCallback,设置的就是Tcp::newConnection,有新用户连接时,响应的就是这个函数
  2. 通过轮询算法选择subLoopnewConnection创建TcpConnection对象并且注册回调,closeCallback->TcpServer::removeConnection
    ioloop->runInLoop->TcpConnection::connectionEstablished
  3. 调用start()函数用于启动,首先调用threadPool.start(startCallback),最终就是创建子线程并开启loop.loop()
  4. 然后调用_loop_->runInLoop(std::bind(&Acceptor::listen, _acceptor_.get()));,就是将Acceptor注册
  5. 开启baseloop.loop()

标签:muduo,Reactor,epoll,阻塞,笔记,学习,调用,IO,loop
From: https://www.cnblogs.com/Lhh-9999/p/17468815.html

相关文章

  • 【React工作记录九十五】前端小知识点扫盲笔记记录4
    前言我是歌谣最好的种树是十年前其次是现在微信公众号关注前端小歌谣带你进入氛围极好的前端巅峰人才交流群url参数解析成一个对象<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge">......
  • linux脚本书写笔记
    6月9日,记录init.d的S40network解析判断是否存在某文件: 此语句为判断目录/var/run是否存在(!-e/var/run),如果不存在则创建该目录(mkdir-p/var/run)。其中,!-e是一个逻辑运算符,用于判断文件或目录是否存在,而mkdir命令的-p选项表示如果需要的话,也会创建所有必要的父级目录。......
  • Python基础语法学习
    基础语法1、常量、表达式print(1+2-4)print(1+3*4)形如:1+2-3这个就叫表达式,表达式的结果叫做叫做返回值123这样的数字称为字面值常量,+-*叫做运算符注意在py中2/3=0.66666而不是c语言中的0在C中整数除整数结果还是整数且会把小数直接舍去,在编程中一般不会有......
  • 010 数据库学习笔记 日期 + 时间 + 星期
    星期获取操作--设置语言,这个很重要,会导致不同的返回结果(只需设置一次语言后,就可以重复调用DATENAME)SETLANGUAGEN'SimplifiedChinese'--简体中文--SETLANGUAGEN'English'--英文--SETLANGUAGEN'Korean'--韩文--获取指定日期为星期几GETDATE()当天日期,GETDATE(......
  • O2OA (翱途) 开发平台应用市场云笔记功能邀您来体验
    O2OA云笔记提供了一个给员工记录工作笔记,在线协同编辑文档,白板演示的工具,该功能可以将记录下来的文档信息件实时同步到云端,用户随时在多个设备上进行查看、编辑与分享,支持在“云”上做笔记、管理文档、编写脑图信息。这样可以帮助整体工作团队实现资料共享、协同编辑、在线实......
  • 适合中小学学生初次学习编程语言Scratch
    2023年4月接触了Scratch,不用写代码,全图形化,拖动图标即可完成编程,简单几步能做出‘切西瓜'等小游戏或效果。入门简单Scratch适合中小学学生初次学习编程语言时使用,尤其是没有编程基础或编程基础较少的孩子,用来进行编程启蒙最合适不过了。 内容丰富Scratch编程内容丰富,形式多......
  • batch_norm在强化学习中建议使用的形式
    defbatch_norm(layer,**kwargs):"""Applybatchnormalizationtoanexistinglayer.Thisisaconveniencefunctionmodifyinganexistinglayertoincludebatchnormalization:Itwillstealthelayer'snonlinearityift......
  • 有什么Windows电脑上好用地记笔记软件
    当你每天的工作事项非常多时,就会有很多事情需要记住,面对繁琐复杂的各种事项,很多人的记忆力都是有限的,很容易就会忘记工作事项,这应该怎么办呢?其实随着工作量的增加,想要快速、准确的记住琐碎的工作信息,借助一款记笔记软件可以起到事半功倍的作用。一般大多数上班族使用的办公设备都......
  • 在职怎么备考事业单位?合理安排学习时间就用待办软件
    在就业形势愈加严峻的时候,年轻人都倾向于找一个比较稳定的工作岗位,而通过考试获得事业编,进入事业单位考试就是不错的选择。不过对于大多数人来说,想要进入机关事业单位工作一次考试是不能成功的,很多网友就一边工作一边备考,有合适的岗位就去参加考试。不过也有一些职场人士表示,一边......
  • 阅读笔记之《构建之法》五
    第十章典型用户和场景10.1典型用户和典型场景①怎样定义典型用户?我们首先要定义用户的角色。正如戏剧中有正面和反面的角色,软件系统中也有受欢迎的和不受欢迎的典型用户。受欢迎的典型用户——指那些按设计者的期望使用系统的用户,如“网站的购物者”不受欢迎的典型用户—......