(P35)muduo_base库源码分析:muduo库如何支持多线程,multiple reactors

本文详细介绍了muduo库如何通过EventLoopThread和EventLoopThreadPool支持多线程,以及multiplereactors的概念。在muduo中,每个线程拥有一个EventLoop,用于处理相应IO事件。当新的连接到来时,会选择一个线程进行处理。通过实例代码和测试,展示了监听socket、已连接socket的事件处理,以及线程间通信和事件调度的过程。
摘要由CSDN通过智能技术生成

1.muduo库如何支持多线程

  • muduo支持多线程的方式:一个程序有多个EventLoop,一个EventLoop属于一个线程,也就是所谓的one Loop per thread
  • EventLoopThread(IO线程类)
  • EventLoopThreadPool(IO线程池类)
    IO线程池的功能是开启若干个IO线程,并让这些IO线程处于事件循环的状态

2.multiple reactors

  • 每个Reactor都属于一个线程;

  • mainReactor关注的是acceptor,也就是监听socket所关注的事件;

  • subReactor关注的是已连接socket所关注的事件,每次新到一个连接,就选择一个subReactor来处理该连接(也就选择了该Reactor所对应的线程来处理连接);

  • 若没有一个subReactor,那么mainReactor既要处理监听socket和已连接socket的事件;
    在这里插入图片描述

  • eg:35\jmuduo\muduo\net\EventLoopThreadPool.h
    35\jmuduo\muduo\net\EventLoopThreadPool.cc
    35\jmuduo\muduo\net\CMakeLists.txt
    35\jmuduo\muduo\net\TcpServer.cc

  • eg测试:35\jmuduo\tests\Reactor_test09.cc
    35\jmuduo\tests\CMakeLists.txt

  • 测试:
    (1)EventLoop loop;中包含一个boost::scoped_ptr poller_;里面会创建一个epoll_creat(),也就是说3号fd被poll fd所占用,称之为pollfd;第3个fd没有关注其某些事件,就不会调用updateChannel,所以也没有打印出来;
    (2)boost::scoped_ptr timerQueue_;是4号fd,会关注timerQueue_的可读事件,从而调用了updateChannel(),从而调用了epoll的updateChannel();
    (3)int wakeupFd_; wakeupFd_应该等于5;
    (4)接下来是 TcpServer server_;它包含了一个Acceptor,boost::scoped_ptr acceptor_; (5)acceptor_又包含了一个监听socket(Socket acceptSocket_;),是6号fd;
    (6)第七个fd是int idleFd_;第7个fd没有关注其某些事件,就不会调用updateChannel,所以也没有打印出来;
    客户端telnet连接2个过来,服务端的日志如下:
    在这里插入图片描述
    只是运行服务端
    在这里插入图片描述
    当一个telnet连接过来,监听socket产生了可读事件,6这个socket产生了可读事件,打印printActiveChannels,且创建了一个新的socket,fd号=8,需要关注其可读事件
    在这里插入图片描述
    telnet客户端发送数据,此时是socket=8产生了可读事件
    在这里插入图片描述
    在这里插入图片描述

  • eg测试:35\jmuduo\tests\Reactor_test10.cc
    35\jmuduo\tests\CMakeLists.txt

  • 测试:多线程程序的fd的使用情况。telnet启动2个客户端。
    在这里插入图片描述
    在这里插入图片描述
    6号socket就是监听socket
    6号socket就是主线程的EventLoop对象的返回的活跃的Accept通道
    在这里插入图片描述
    接着创建一个新的连接出来,分配一个线程来处理。10是第一个IO线程的EventLoop对象的wakeupFd被唤醒了。
    // 由于当前线程与ioLoop所属的线程不在同一个线程,把connectEstablished加入到ioLoop线程所属的EventLoop队列中
    ioLoop->runInLoop(boost::bind(&TcpConnection::connectEstablished, conn));
    在这里插入图片描述
    在这里插入图片描述
    13号fd被唤醒,与上分析方法类似
    在这里插入图片描述
    客户端发送数据,那么可以看到对应的printActiveChannels的wakeupFd_处理可读事件。下面是2个telnet客户端,发送数据的情况
    在这里插入图片描述
    在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢打篮球的普通人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值