面试(十一)
目录
一.IO多路复用
二.为什么有IO多路复用机制?
三.IO多路复用的三种实现方式
3.1 select
select 函数接口
select 使用示例
select 缺点
3.2 poll
poll函数接口
poll使用示例
poll缺点
3.3 epoll
epoll函数接口
epoll使用示例
epoll缺点
四. 进程和线程的区别
五. 线程和进程的通信方式都有哪些
六. 多线程并发服务器
七. 线程池
八. 深拷贝和浅拷贝
九. 内存泄漏
一.IO多路复用
IO多路复用是一种同步IO模型,实现一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能够通知应用程序进行相应的读写操作;没有文件句柄就绪时会阻塞应用程序,交出CPU,多路是指网络连接,复用指的是同一个线程
二.为什么有IO多路复用机制?
没有IO多路复用机制时,有BIO、NIO两种实现方式,但有一些问题
同步阻塞(BIO)
· 服务端采用单线程,当accept一个请求后,在recv或send调用阻塞时,将无法accept其他请求(必须等上一个请求处recv或send完),无法处理并发
· 服务端采用多线程,当accept一个请求后,开启线程进行recv,可以完成并发处理,当随着请求数增加需要增加系统线程
同步非阻塞(NIO)
· 服务端当accept一个请求后,加入fds集合,每次轮询一遍fds集合recv(非阻塞)数据,没有数据则立即返回错误
IO多路复用
· 服务器端采用单线程通过select/epoll等系统调用获取fd列表,遍历有事件的fd列表,accept/recv/send,使其能支持更多的并发连接请求
三.IO多路复用的三种实现方式
3.1 select
select 函数接口
#include <sys/select.h>
#include <sys/time.h>#define FD_SETSIZE 1024
#define NFDBITS (8 * sizeof(unsigned long))
#define __FDSET_LONGS (FD_SETSIZE/NFDBITS)// 数据结构(bitmap)
// 用来表示一组文件描述符的状态
typedef struct
{unsigned long fds_bits[__FDSET_LONGS];
}fd_set;// API
int select{int max_fd, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout
}// 返回值就绪描述符的数目FD_ZERO(int fd, fd_set* fds) // 清空集合
FD_SET(int fd, fd_set* fds) // 将给定的描述符加入集合
FD_ISSET(int fd, fd_set* fds) // 判断指定描述符是否在集合中
FD_CLR(int fd, fd_set* fds) // 将给定的描述符从文件中删除
select 使用示例
int main()
{/** 这里进行一些初始化的设置,* 包括socket建立,地址的设置等,*/fd_set read_fs, write_fs;struct timeval timeout;int max = 0; // 用于记录最大的fd,在轮询中时刻更新即可// 初始化比特位FD_ZERO(&read_fs);FD_ZERO(&write_fs);int nfds = 0; // 记录就绪的事件,可以减少遍历的次数while (1) {// 阻塞获取// 每次需要把fd从用户态拷贝到内核态nfds = select(max + 1, &read_fd, &write_fd, NULL, &timeout);// 每次需要遍历所有fd,判断有无读写事件发生for (int i = 0; i <= max && nfds; ++i) {if (i == listenfd) {--nfds;// 这里处理accept事件FD_SET(i, &read_fd);//将客户端socket加入到集合中}if (FD_ISSET(i, &read_fd)) {--nfds;// 这里处理read事件}if (FD_ISSET(i, &write_fd)) {--nfds;// 这里处理write事件}}}
select 缺点
· 单个进程所打开的FD是有限制的,通过 FD_SETSIZE 设置,默认 1024
· 每次调用 select ,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大
· 对 socket 扫描时是线性扫描,采用轮询的方法,效率较低(高并发时)
3.2 poll
poll函数接口
poll与select相比,只是没有fd的限制,其它基本一样
#include <poll.h>
// 数据结构
struct pollfd {int fd; // 需要监视的文件描述符short events; // 需要内核监视的事件short revents; // 实际发生的事件
};// API
int poll(struct pollfd fds[], nfds_t nfds, int timeout);
poll使用示例
// 先宏定义长度
#define MAX_POLLFD_LEN 4096 int main() {/** 在这里进行一些初始化的操作,* 比如初始化数据和socket等。*/int nfds = 0;pollfd fds[MAX_POLLFD_LEN];memset(fds, 0, sizeof(fds));fds[0].fd = listenfd;fds[0].events = POLLRDNORM;int max = 0; // 队列的实际长度,是一个随时更新的,也可以自定义其他的int timeout = 0;int current_size = max;while (1) {// 阻塞获取// 每次需要把fd从用户态拷贝到内核态nfds = poll(fds, max+1, timeout);if (fds[0].revents & POLLRDNORM) {// 这里处理accept事件connfd = accept(listenfd);//将新的描述符添加到读描述符集合中}// 每次需要遍历所有fd,判断有无读写事件发生for (int i = 1; i < max; ++i) { if (fds[i].revents & POLLRDNORM) { sockfd = fds[i].fdif ((n = read(sockfd, buf, MAXLINE)) <= 0) {// 这里处理read事件if (n == 0) {close(sockfd);fds[i].fd = -1;}} else {// 这里处理write事件 }if (--nfds <= 0) {break; } }}}
poll缺点
· 每次调用 poll ,都需要把 fd 集合从用户态拷贝到内核态,这个开销在 fd 很多时会很大
· 对 socket 扫描时是线性扫描,采用轮询的方法,效率较低
3.3 epoll
epoll函数接口
#include <sys/epoll.h>// 数据结构
// 每一个epoll对象都有一个独立的eventpoll结构体
// 用于存放通过epoll_ctl方法向epoll对象中添加进来的事件
// epoll_wait检查是否有事件发生时,只需要检查eventpoll对象中的rdlist双链表中是否有epitem元素即可
struct eventpoll {/*红黑树的根节点,这颗树中存储着所有添加到epoll中的需要监控的事件*/struct rb_root rbr;/*双链表中则存放着将要通过epoll_wait返回给用户的满足条件的事件*/struct list_head rdlist;
};// APIint epoll_create(int size); // 内核中间加一个 ep 对象,把所有需要监听的 socket 都放到 ep 对象中
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); // epoll_ctl 负责把 socket 增加、删除到内核红黑树
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);// epoll_wait 负责检测可读队列,没有可读 socket 则阻塞进程
epoll使用示例
int main(int argc, char* argv[])
{/** 在这里进行一些初始化的操作,* 比如初始化数据和socket等。*/// 内核中创建ep对象epfd=epoll_create(256);// 需要监听的socket放到ep中epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev);while(1) {// 阻塞获取nfds = epoll_wait(epfd,events,20,0);for(i=0;i<nfds;++i) {if(events[i].data.fd==listenfd) {// 这里处理accept事件connfd = accept(listenfd);// 接收新连接写到内核对象中epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&ev);} else if (events[i].events&EPOLLIN) {// 这里处理read事件read(sockfd, BUF, MAXLINE);//读完后准备写epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);} else if(events[i].events&EPOLLOUT) {// 这里处理write事件write(sockfd, BUF, n);//写完后准备读epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);}}}return 0;
}
epoll缺点
epoll只能工作在linux下
四. 进程和线程的区别
· 进程是资源分配的最小单位,线程是 CPU 调度的最小单位
· 一个进程可以包含多个线程,一个线程只能属于一个进程
· 进程间内存空间独立,线程间共享同一个内存地址
五. 线程和进程的通信方式都有哪些
线程间的通信
1. 共享内存:同一进程内的所有线程共享相同的地址空间,所以一个线程可以直接访问另一个线程的数据
2. 互斥锁:任何时刻只有一个线程可以访问该资源
3. 条件变量:允许线程在某个条件满足之前阻塞等待,当条件满足时被唤醒
4. 信号量:可以用来控制对共享资源的访问次数
5. 原子操作:提供了一种无需额外同步机制即可安全地更新共享数据的方法
进程间的通信
1. 管道:一种半双工的通信方式,适用于父子进程之间或者具有亲缘关系的进程之间进行通信
2. 命名管道:可以在不相关的进程之间使用,并且可以持久化到文件系统中
3. 消息队列:允许多个进程以队列的形式发送和接收信息
4. 共享内存:进程间可以通过映射同一段物理内存来进行高速数据交换
5. 信号
6. 套接字
六. 多线程并发服务器
多线程并发服务器是一种能够同时处理多个客户端请求的服务器架构
七. 线程池
线程池是一种用于管理和复用线程的技术,它预先创建了一组线程,并将这些线程保存在池中。当有任务需要执行时,从线程池中取出一个空闲的线程来处理任务,任务完成后该线程不会被销毁而是返回到线程池中等待下一次使用。这种方式可以减少频繁创建和销毁线程带来的开销。
八. 深拷贝和浅拷贝
浅拷贝:浅拷贝创建了一个新的对象,然后将原始对象中所有可变引起的对象直接复制到新对象中。
深拷贝:创建了一个新的对象,还会递归地复制原始对象中的所有子对象。新对象与原始对象完全独立,互不影响
九. 内存泄漏
程序在申请内存后,未能释放不再使用的内存。
解决措施:
1.释放资源
2.使用智能指针,自动管理生命周期
3.对象池,防止频繁创建
4.避免使用全局变量
相关文章:
面试(十一)
目录 一.IO多路复用 二.为什么有IO多路复用机制? 三.IO多路复用的三种实现方式 3.1 select select 函数接口 select 使用示例 select 缺点 3.2 poll poll函数接口 poll使用示例 poll缺点 3.3 epoll epoll函数接口 epoll使用示例 epoll缺点 四. 进程和线程的区别…...
React-useState的使用
useState 是 React 提供的一个 Hook,允许你在函数组件中添加和管理状态(state)。在类组件中,状态管理通常是通过 this.state 和 this.setState 来实现的,而在函数组件中,useState 提供了类似的功能。 基本…...
设计模式之破环单例模式和阻止破坏
目录 1. 序列化和反序列化2. 反射 这里单例模式就不多说了 23种设计模式之单例模式 1. 序列化和反序列化 这里用饿汉式来做例子 LazySingleton import java.io.Serializable;public class LazySingleton implements Serializable {private static LazySingleton lazySinglet…...
11.19c++面向对象+单例模式
编写如下类: class File{ FILE* fp }; 1:构造函数,打开一个指定的文件 2:write函数 向文件中写入数据 3:read函数,从文件中读取数据,以string类型返回 代码实现: #include <iostream>using namespace std;class…...
一文了解TensorFlow是什么
TensorFlow是一个开源的机器学习框架,由Google开发并维护。它提供了一个灵活且高效的环境,用于构建和训练各种机器学习模型。 TensorFlow的基本概念包括: 张量(Tensor):TensorFlow中的核心数据结构&#x…...
如何做好一份技术文档?
打造出色技术文档的艺术 在当今技术驱动的世界中,技术文档扮演着至关重要的角色。它不仅是工程师和开发人员之间交流的桥梁,更是产品和技术成功的隐形推手。一份优秀的技术文档宛如一张精准的航海图,能够引导读者穿越技术的迷雾,…...
Linux和Ubuntu的关系
Linux和Ubuntu的关系: 1. Linux本身是内核,Ubuntu系统是基于Linux内核的操作系统。 2. Linux内核操作系统的构成: 内核、shell、文件系统、应用程序 -应用程序:文本编辑器等 -文件系统:文件存放在存储设备上的组织方…...
软件工程之静态建模
静态模型:有助于设计包、类名、属性和方法特征标记(但不是方法体)的定义,例如UML类图。 用例的关系: 扩展关系: 扩展关系允许一个用例(可选)扩展另一个用例(基用例&…...
PICO VR串流调试Unity程序
在平时写Unity的VR程序的时候,需要调试自己写的代码,但是有的时候会发现场景过于复杂,不是HMD一体机能运行的,或者为了能够更方便的调试,不需要每次都将程序部署到眼睛里,这样非常浪费时间,对于…...
自媒体图文视频自动生成软件|03| 页面和结构介绍
代码获取方式在文本末尾🔚 *代码获取方式在文本末尾🔚 *代码获取方式在文本末尾🔚 *代码获取方式在文本末尾🔚 视频图片生成器 一个基于 Python 和 Web 的工具,用于生成带有文字和语音的视频以及图片。支持多种尺寸、…...
深入浅出摸透AIGC文生图产品SD(Stable Diffusion)
hihi,朋友们,时隔半年(24年11月),终于能腾出时间唠一唠SD了🤣,真怕再不唠一唠,就轮不到SD了,技术更新换代是在是太快! 朋友们,最近(24年2月)是真的没时间整理笔记,每天都在疯狂的学习Stable Diffusion和WebUI & ComfyUI,工作实在有点忙,实践期间在飞书上…...
解析生成对抗网络(GAN):原理与应用
目录 一、引言 二、生成对抗网络原理 (一)基本架构 (二)训练过程 三、生成对抗网络的应用 (一)图像生成 无条件图像生成: (二)数据增强 (三ÿ…...
CodeIgniter URL结构
CodeIgniter 的URL 结构设计得简洁且易于管理。通常遵循以下模式: http://<domain>/<index_page>/<controller>/<method>/<parameters> 下面是每个部分的详细说明: <domain>: 这是你的网站域名&#…...
从 App Search 到 Elasticsearch — 挖掘搜索的未来
作者:来自 Elastic Nick Chow App Search 将在 9.0 版本中停用,但 Elasticsearch 拥有你构建强大的 AI 搜索体验所需的一切。以下是你需要了解的内容。 生成式人工智能的最新进展正在改变用户行为,激励开发人员创造更具活力、更直观、更引人入…...
鸿蒙本地模拟器 模拟TCP服务端的过程
鸿蒙模拟器模拟TCP服务端的过程涉及几个关键步骤,主要包括创建TCPSocketServer实例、绑定IP地址和端口、监听连接请求、接收和发送数据以及处理连接事件。以下是详细的模拟过程: **1.创建TCPSocketServer实例:**首先,需要导入鸿蒙…...
Qt/C++基于重力模拟的像素点水平堆叠效果
本文将深入解析一个基于 Qt/C 的像素点模拟程序。程序通过 重力作用,将随机分布的像素点下落并水平堆叠,同时支持窗口动态拉伸后重新计算像素点分布。 程序功能概述 随机生成像素点:程序在初始化时随机生成一定数量的像素点,每个…...
Zookeeper学习心得
本人学zookeeper时按照此文路线学的 Zookeeper学习大纲 - 似懂非懂视为不懂 - 博客园 一、Zookeeper安装 ZooKeeper 入门教程 - Java陈序员 - 博客园 Docker安装Zookeeper教程(超详细)_docker 安装zk-CSDN博客 二、 zookeeper的数据模型 ZooKeepe…...
嵌入式开发工程师面试题 - 2024/11/24
原文嵌入式开发工程师面试题 - 2024/11/24 转载请注明来源 1.若有以下定义语句double a[8],*pa;int i5;对数组元素错误的引用是? A *a B a[5] C *(p1) D p[8] 解析: 在 C 或 C 语言中&am…...
Python中打印当前目录文件树的脚本
效果图: 实现脚本: 1、显示所有文件和文件夹: import osdef list_files(startpath, prefix):items os.listdir(startpath)items.sort()for index, item in enumerate(items):item_path os.path.join(startpath, item)is_last index le…...
全景图像(Panorama Image)向透视图像(Perspective Image)的跨视图转化(Cross-view)
一、概念讲解 全景图像到透视图像的转化是一个复杂的图像处理过程,它涉及到将一个360度的全景图像转换为一个具有透视效果的图像,这种图像更接近于人眼观察世界的方式。全景图像通常是一个矩形图像,它通过将球面图像映射到平面上得到…...
小红书笔记API避坑指南:数据结构解析与常见错误排查
小红书笔记API避坑指南:数据结构解析与常见错误排查 在小红书生态中,API作为连接开发者与平台数据的桥梁,其重要性不言而喻。但许多开发者在实际调用过程中,常常陷入数据结构理解不透、错误排查效率低下的困境。本文将从小红书笔记…...
终极实战指南:在Docker容器中运行Windows系统的完整解决方案
终极实战指南:在Docker容器中运行Windows系统的完整解决方案 【免费下载链接】windows Windows inside a Docker container. 项目地址: https://gitcode.com/GitHub_Trending/wi/windows 还在为Windows虚拟机占用大量系统资源而烦恼吗?想体验在容…...
人脸检测开源生态新成员:cv_resnet101_face-detection_cvpr22papermogface ModelScope集成详解
人脸检测开源生态新成员:cv_resnet101_face-detection_cvpr22papermogface ModelScope集成详解 1. 项目概述 今天要介绍的是一个特别实用的人脸检测工具——基于MogFace模型开发的本地高精度人脸检测系统。这个工具解决了PyTorch新版本加载旧模型的兼容性问题&…...
java的for循环
public class Demo6 {public static void main(String[] args) {for (int money1;money<10;money){System.out.println("换一元纸币"money"张。换5角硬币"(10-money)*2"个");}} }public class Demo8 {public static void main(String[] args)…...
Pixel Fashion Atelier入门必看:Forge!按钮物理位移反馈的CSS3实现原理
Pixel Fashion Atelier入门必看:Forge!按钮物理位移反馈的CSS3实现原理 1. 引言:像素世界的物理交互 在Pixel Fashion Atelier这款独特的图像生成工具中,最令人印象深刻的莫过于那个醒目的橙色"锻造"按钮。当用户点击时ÿ…...
基于人工电场搜索智能优化算法的水库发电和供水优化调度
基于人工电场搜索智能优化算法的水库发电和供水优化调度; 代码为MATLAB编写,可直接运行; 含有实例数据,点击即可运行,替换成自己数据点击即可出结果,如图。在水库管理中,实现发电和供水的优化调…...
在给ppt接入扣子空间(Ai)/智能体,新玩法10分钟搞定说课,公开课AI互动!
做 PPT 时,你是否遇到过这些痛点:演讲中观众突然提问,临时组织语言容易逻辑混乱;同一问题被反复询问,浪费演示时间;静态页面无法按需补充细节,信息传递不精准。而扣子空间(Coze&…...
FPGA时序约束实战:input delay约束的5个常见坑点及解决方法
FPGA时序约束实战:input delay约束的5个常见坑点及解决方法 在FPGA开发中,时序约束的正确设置往往是项目成败的关键。我曾在一个高速数据采集项目中,因为input delay约束设置不当,导致系统在高温环境下出现偶发性数据错误…...
【NR 定位】3GPP NR Positioning 5G定位标准解读(七):RRC_INACTIVE状态下的高效定位机制
1. RRC_INACTIVE状态下的5G定位挑战与机遇 在5G网络中,RRC_INACTIVE状态是一种独特的节能模式,它允许设备在保持部分网络连接的同时大幅降低功耗。这种状态特别适合物联网设备,比如智能电表、资产追踪器和可穿戴设备。想象一下你家的智能门锁…...
从游戏排行榜到实时榜单:手把手用无旋Treap(Fhq Treap)实现一个高性能排名系统
从游戏排行榜到实时榜单:手把手用无旋Treap(Fhq Treap)实现一个高性能排名系统 在当今的互联网应用中,实时排名系统无处不在——从游戏中的玩家战力榜,到直播平台的礼物贡献榜,再到电商的热销商品排行。这些…...
