Linux muduo 网络库常见问题

主要示意图和知识点框架:

1、阻塞、非阻塞、同步、异步在这里插入图片描述
在处理IO的时候,阻塞和非阻塞都是同步IO,只有使用了特殊的API才是异步IO。

2、五种IO模型:
阻塞、非阻塞、IO复用、信号驱动、异步IO

3、muduo网络库给用户提供了两个主要的类:

TcpServer : 用于编写服务器程序的
TcpClient : 用于编写客户端程序的

采用epoll + 线程池的方式

好处:能够把网络IO的代码和业务代码区分开来 - 处理用户的连接断开 用户的可读可写

在这里插入图片描述

常见问题

1、采用 one loop per thread 线程模型并向上封装线程池,避免线程创建和销毁带来的性能开销。请问线程池是如何提高性能的?

(1)、减少线程创建和销毁的开销
线程的创建和销毁在操作系统中是相对昂贵的操作。每次创建一个新线程,都需要系统分配栈内存、初始化线程控制块(Thread Control Block),以及与操作系统调度器交互。而销毁线程则涉及到清理线程的资源。这些操作在高并发场景下非常耗时,尤其是当大量请求到达时,频繁的线程创建和销毁会严重影响程序的响应能力。
线程池通过预先创建一定数量的线程,并将它们保持在空闲状态。当任务到来时,直接从线程池中取出一个空闲的线程来执行任务,避免了频繁的线程创建和销毁所带来的开销。

(2)、避免上下文切换带来的开销
每个线程都需要一些计算资源进行管理,当线程数超出处理器核心数时,操作系统需要在多个线程之间切换执行(即上下文切换)。上下文切换会保存当前线程的状态并加载另一个线程的状态,这个过程会引入性能开销。
线程池通过控制线程的数量,避免创建过多的线程,使得系统中活跃的线程数量能够与 CPU 核心数相匹配,尽量做到高并发。

(3)、线程复用
线程池中的线程是复用的。当一个线程执行完一个任务后,它不会销毁,而是返回到线程池中继续等待分配新的任务。这种复用机制减少了多次创建和销毁线程带来的性能开销,同时可以减少内存碎片。

2、只用socket系统调用获得一个文件描述符,不bind,放入epoll中,什么时候会触发?

相当于监听所有网卡、所有端口。

3、I/O多路复用中 select、poll、epoll 的区别?

  • 底层数据结构不同:select是数组,poll是链表,epoll是红黑树和双链表。因此select在32位系统上只能支持1024个最大连接,poll和epoll则都没有限制。
  • 获取就绪fd方式不同:select和poll都是遍历,epoll是事件回调(避免了轮询,回调函数将就绪的描述符添加到一个链表中,执行epoll_wait时,返回这个链表,muduo中是个数组)。
  • fd数据拷贝方式不同:每次调用select和poll,都需要将fd数据从用户空间拷贝到内核空间,而epoll则使用内存映射机制(mmap),无需从用户空间频繁拷贝数据到内核空间。
    在这里插入图片描述

补充:内存映射(Memory-mapped I/O)是将磁盘文件的数据映射到内存,用户通过修改内存就能修改磁盘文件

epoll优势:
1)用户态调用epoll_create()在内核中建立一个epoll对象(在epoll文件系统中为这个句柄对象分配资源) 并返回一个文件描述符,该文件描述符用于后续对该 epoll 对象进行操作。

2)调用epoll_ctl向epoll对象中添加这100万个连接的套接字,红黑树。

3)调用epoll_wait收集发生的事件的fd资源(从红黑树节点中摘录出发生事件的节点,放到双向链表中 《返回一个发生事件集合》)

select、poll、epoll 原理
select、poll、epoll 区别

4、muduo网络库与webserver的区别?

简单解释:

Muduo本身并不是一个应用程序,而是一个网络库,专注于高效的事件处理、线程池管理、定时器、异步I/O等。

WebServer项目的目的是提供一个可以实际运行的HTTP服务器,用户可以通过浏览器或其他客户端访问它。

详细解释 :

Muduo是 一个轻量级的C++网络库,主要用于构建高性能的服务器端应用。它的目的是提供一个易于使用的事件驱动框架,帮助开发者快速构建高性能的并发服务器

WebServer 通常指的是一个具体的HTTP服务器项目,用于处理客户端的HTTP请求,返回静态或动态内容。它通常包括请求解析、路由处理、静态文件服务、会话管理、负载均衡等功能。

Muduo:Muduo 适用于需要高并发处理的服务器端应用的开发,比如高性能的网络服务、消息队列、游戏服务器等。开发者可以基于 Muduo 构建各种定制的网络服务。

WebServer:WebServer 直接用于提供Web服务,是实际运行在生产环境中的应用程序。它们通常部署在Web服务器或应用服务器上,用于提供网页、API接口等服务。

Muduo:Muduo 处于较低的抽象层次,专注于提供网络编程的基础设施,开发者需要基于 Muduo 自行构建具体的应用逻辑。它是一个库,需要较高的编程技巧和对网络编程的理解。

WebServer:WebServer 项目通常处于较高的抽象层次,直接提供 HTTP 服务功能。开发者可以专注于处理业务逻辑,而不必关心底层的网络 I/O 细节。

问题:那我在muduo上面加一个协议层,将muduo获取到的数据以HTTP协议的格式进行解析,然后加几条路由进行业务处理,处理完毕后再组织成HTTP格式数据进行响应,是不是就相当于实现了一个高性能的WebServer?算是对muduo简单的拓展?
回答:是的

5、使用Epoll + LT模式的I/O复用模型,并结合非阻塞I/O实现主从Reactor模型

主从Reactor模型:

建立连接IO事件监听/读写以及事件分发 两部分用不同的线程处理,这样各司其职,能有效利用系统多核资源;同时为提高事件处理的效率,通常可以使用线程池来处理 IO事件监听/读写以及事件分发 这部分操作。
在这里插入图片描述
MainReactor 只负责监听派发新连接,在 MainReactor 中通过 Acceptor 接收新连接并轮询派发给 SubReactor,SubReactor 负责此连接的读写事件。

epoll+非阻塞I/O:

如果使用 水平触发 模式,当内核通知文件描述符可读写时,接下来还可以继续去检测它的状态,看它是否依然可读或可写。所以在收到通知后,没必要一次执行尽可能多的读写操作,所以搭配阻塞 IO 是可行的。

如果使用 边缘触发 模式,IO 事件发生时只会通知一次,而且我们不知道到底能读写多少数据,所以在收到通知后应尽可能地读写数据,以免错失读写的机会。因此,我们会循环从文件描述符读写数据,那么如果文件描述符是阻塞的,没有数据可读写时,进程会阻塞在读写函数那里,程序就没办法继续往下执行。所以,边缘触发模式一般和非阻塞 IO 搭配使用,程序会一直执行 IO 操作,直到系统调用(如 read 和 write)返回错误,错误类型为 EAGAIN 或 EWOULDBLOCK。
另外,使用 IO 多路复用时,推荐搭配非阻塞 IO 一起使用。

6、项目技术栈

智能指针:
(1)unique_ptr:独占所有权,确保资源在作用域结束时能被正确释放。
一个TcpConnection对象对应一个channel对象和一个socket套接字:

TcpConnection.h
// 这里和Acceptor类似   Acceptor在mainloop里,TcpConnection在subloop里
std::unique_ptr<Socket> socket_;
std::unique_ptr<Channel> channel_;

(2)shared_ptr:多个指针需要共享同一块内存的情况,采用引用计数来管理内存释放。

(3)weak_ptr:用于解决shared_ptr可能导致的循环引用问题。

观察者模式:

std::weak_ptr<void> tie_;
tie_ = shared_ptr<void> TcpConnectionObj;
std::shared_ptr<void> guard = tie_.lock();
if (guard)
{
......
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值