中间件
  • 【C++】从零实现 C++ 自定义 list 容器:双向链表与迭代器深度解析

    1. 引言 在 C++ 中,STL list 容器提供了双向链表的实现,适用于需要频繁插入和删除的场景。本文将手把手带你实现一个自定义的 list 容器,详细解析双向链表的节点设计、迭代器实现、增删操作等。希望通过本文的学习,你能对链表的底层原理有更深入的理解,并学会如何用 C++ 实现一个高效的 list 容器。 📌 2. 内容概要 双向链表的基本结构设计 自定义迭代器的实现原理 核心方法实现:push_back、insert、erase等 内存管理与析构函数 性能分析与应用场景 📌 3. list 容器结构设计 ✨ 3.1 节点结构设计 在双向链表中,每个节点包含数据域和两个指针域,分别指向前后节点。我们首先定义节点的结构体 list_node,用于存储数据和链接信息。 template<class T> struct list_node { T _data; list_node<T>* _prev; list_node<T>* _next; list_node(const T& data = T()) : _data(data), _prev(nullptr), _next(nullptr) {} }; 代码解读: _data:存储节点的数据。 _prev 和 _next:分别指向前一个和后一个节点,形成双向链接。 ✨ 3.2 自定义迭代器的实现 list 容器需要一个迭代器来支持前向和后向遍历。我们设计一个 list_iterator,封装节点指针,并重载 *、->、++、-- 等操作符。 template<class T, class Ref, class Ptr> struct list_iterator { typedef list_node<T> Node; Node* _node; list_iterator(Node* node = nullptr) : _node(node) {} Ref operator*() { return _node->_data; } Ptr operator->() { return &_node->_data; } list_iterator& operator++() { _node = _node->_next; return *this; } list_iterator operator++(int) { list_iterator tmp(*this); _node = _node->_next; return tmp; } list_iterator& operator--() { _node……

    SE_Wang 2024-12-17
    6 0 0
  • H3C UniServer B5700 G3

    OS兼容性查询结果:共查询到51条符合要求的数据。 OS版本 OS认证链接 说明 Asianux Server 7.3 (64 bit) 链接 Asianux Server 7.6 (64 bit) 链接 CAS-E0526 CAS-E0530 CAS-E0536 CAS-E0705 CentOS 7.4 (64 bit) 说明23 CentOS 7.5 (64 bit) 说明24 CentOS 7.6 (64 bit) 说明25 CentOS 8 (64 bit) 说明28 Citrix Hypervisor 8.0 (64 bit) Citrix XenServer 7.3 (64 bit) Citrix XenServer 7.4 (64 bit) Citrix XenServer 7.5 (64 bit) Citrix XenServer 7.6 (64 bit) 链接 CloudOS Microsoft Hyper-V Server 2012 R2 链接 Microsoft Hyper-V Server 2016 链接 Microsoft Hyper-V Server 2019 Microsoft Windows Server 2012 R2 链接 Microsoft Windows Server 2016 链接 Microsoft Windows Server 2019 Onestor Red Hat Enterprise Linux 6.9 (64 bit) (includes KVM) 链接 说明32 Red Hat Enterprise Linux 7.3 (64 bit) (includes KVM) 链接 说明35 Red Hat Enterprise Linux 7.4 (64 bit) (includes KVM) 链接 说明36 Red Hat Enterprise Linux 7.5 (64 bit) (includes KVM) 链接 说明37 Red Hat Enterprise Linux 7.6 (64 bit) (includes KVM) 链接 说明38 Red Hat Enterprise Linux 8 (64 bit) (includes KVM) 说明41 SLES 12 (64 bit) SP2 (includes XEN & KVM) 说明46;说明76 SLES 12 (64 bit) SP3 (includes XEN & KVM) 链接 说明47;说明76 SLES 12 (64 bit) SP4 (includes XEN & KVM) 链接 说明76 SLES 15 (64 bit) (includes XEN & KVM) 链接 说明48;说明76 SLES 15 (64 bit) SP1 (includes XEN & KVM) 说明49;说明76 Ubuntu Server 17.10 (64 bit) – LTS 说……

    SE_Gai 2024-12-17
    4 0 0
  • Linux 内核日志系统—printk的机制与应用

    1.内核代码 linux 4.9.88: kernel/printk.c📎printk.c include/linux/kernel.h📎kernel.h kernel/printk/internal.h📎internal.h 在 Linux 内核开发中,**printk** 是最常用的调试工具之一,主要用于输出内核日志信息。printk 不仅类似用户空间的 printf,还提供了日志级别管理功能,通过指定日志级别(如 KERN_WARNING),可以精准控制日志信息的输出范围和重要性。本文系统梳理了 printk 的使用方法、日志级别管理、日志信息的存储位置,以及输出过程的核心机制。通过解析源码和示例,详细展示了如何利用 console_loglevel 等宏调控日志输出行为,并剖析了内核是如何通过 call_console_drivers 将日志发送到不同设备。 2.printk的使用 2.1 使用实例 调试内核、驱动的最简单方法,是使用printk函数打印信息。 printk函数与用户空间的printf函数格式完全相同,它所打印的字符串头部可以加入“\001n”样式的字符。 其中n为0~7,表示这条信息的记录级别,n数值越小级别越高。 注意:linux 2.x内核里,打印级别是用""来表示。 在驱动程序中,可以这样使用printk: printk("This is an example\n"); printk("\0014This is an example\n"); printk("\0014""This is an example\n"); printk(KERN_WARNING"This is an example\n"); 在上述例子中: 第一条语句没有明确表明打印级别,它被处理前内核会在前面添加默认的打印级别:“<4>” KERN_WARNING是一个宏,它也表示打印级别: #define KERN_SOH "\001" /* ASCII Start Of Header */ #define KERN_WARNING KERN_SOH "4" /* warning conditions */ 现在知道了,内核的每条打印信息都有自己的级别,当自己的级别在数值上小于某个阈值时,内核才会打印该信息。 2.2 printk的记录级别 在内核代码include/linux/kernel.h中,下面几个宏确定了printk函数怎么处理打印级别……

    SE_Wang 2024-12-16
    16 0 0
  • 【Linux】进程字段、环境变量与进程地址空间

    一、查看进程字段 在Linux下,可以使用ps指令显示当前系统运行的进程信息,包含进程状态、资源使用情况等内容ps的-l选项可以显示长格式信息,包括F(标志)、S(状态)、UID、PID等详细字段: F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 1.字段说明 下面是对字段的解释说明: 字段 含义 F 标志位(Flags)。与进程状态和调度相关的标志,常见值: - 0:普通进程,通常是非前台组成员的用户进程 - 1:前台进程组成员,通常是终端运行的交互式程序 - 4:由超级用户(root 用户)创建的进程 - 10:系统不可杀的进程,如核心守护进程 S 进程状态(State)。表示进程当前的状态,可能的值: - R:运行(Runnable) - S:睡眠(Sleeping) - D:不可中断睡眠(Uninterruptible Sleep) - Z:僵尸进程(Zombie) - T:停止(Stopped) UID 用户 ID(User ID)。表示运行此进程的用户的 ID,即执行者的身份 - 0:超级用户(root),拥有最高权限 - 1-99:通常保留给系统用户(例如 daemon、bin) - 1000 及以上:普通用户 PID 进程 ID(Process ID)系统中每个运行进程的唯一标识符 PPID 父进程 ID(Parent Process ID)表示创建该进程的父进程的 PID C CPU 使用率(CPU utilization)表示进程使用 CPU 的相对时间(以百分比表示) PRI 优先级(Priority)进程当前的调度优先级,数值越低优先级越高 NI Nice 值(Niceness)影响进程优先级的用户调整值,范围为 -20(最高优先级)到 19(最低优先级) ADDR 内存地址(memory address)与进程的内存映射相关,通常显示为 -,表示不适用 SZ 内存大小(Size)表示进程的虚拟内存大小(以页为单位) WCHAN 等待通道(Wait Channel)如果进程正在等待资源或事件,则显示等待的内核函数名,否则为 - TTY 终端(Terminal)表示与进程关联的终端设备名 - 如果是后台进程……

    SE_Wang 2024-12-13
    7 0 0
  • 【Linux | 计网】TCP协议深度解析:从连接管理到流量控制与滑动窗口

    1、三次握手和四次挥手的联系: 其实四次挥手本质上与三次握手的流程一样的。此话怎讲? 三次握手的本质,其实也是4次握手,只不过中间两次被合并了(ACK和FIN合并了)! 为什么挥手必须要将ACK和FIN分开呢? 挥手的时候可以将ACK和FIN一起发送吗 在三次握手的时候,可以直接将SYN和ACK进行合并发送, 但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,“你发的FIN报文我收到了”。 只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。 客户端想要断开连接发送FIN,服务器收到之后发送ACK应答,但是服务器在大多数情况下是不会立刻断开连接,因为可能还有业务没有处理完,所以ACK和FIN之间一定有一个时间差,这就导致了ACK不能和FIN一起发送 我们在挥手流程图有这样几个状态,分别是 TIME_WAIT , CLOSE_WAIT,FIN_WAIT。 2.理解 CLOSE_WAIT 状态 CLOSE_WAIT 状态存在的意义: CLOSE_WAIT是连接被动关闭方在收到对方发送的FIN请求后,发送ACK确认进入的状态。在这个状态下,应用程序可能还有未处理的数据需要发送,因此需要等待应用程序处理完这些数据后,才能发送FIN请求来关闭连接。如果应用程序没有及时关闭连接,可能会导致大量的CLOSE_WAIT状态,从而消耗系统资源。CLOSE_WAIT状态表示被动关闭方正在等待关闭,没有真正关闭。 CLOSE_WAIT状态的特点 双向关闭的一部分:TCP连接是双向的,需要两端都同意关闭连接才能完全关闭。CLOSE_WAIT状态表示本地端(即接收ACK的一端)已经收到了对方的关闭请求,并发送了确认,但还在等待本地端的应用程序或系统发送关闭请求以完成连接的关闭。 等待远程FIN报文:在CLOSE_WAIT状态下,本地端会等待远程端发送FIN报文来关闭连接。如果远程端没有发送FIN报文……

    SE_Wang 2024-12-12
    19 0 0
  • 安全运维:cmd命令大全(108个)

    1、calc:启动计算器 2、appwiz.cpl:程序和功能 3、certmgr.msc:证书管理实用程序 4、charmap:启动字符映射表 5、chkdsk.exe:Chkdsk磁盘检查(管理员身份运行命令提示符) 6、cleanmgr: 打开磁盘清理工具 7、cliconfg:SQL SERVER 客户端网络实用工具 8、cmstp:连接管理器配置文件安装程序 9、cmd.exe:CMD命令提示符 10、自动关机命令: Shutdown -s -t 30:表示30秒后自动关机,中间带有空格。 shutdown -a :取消定时关机 Shutdown -r -t 30:表示30秒后自动重新启动 rundll32 user32.dll,LockWorkStation:表示锁定计算机 11、colorcpl:颜色管理,配置显示器和打印机等中的色彩 12、CompMgmtLauncher:计算机管理 13、compmgmt.msc:计算机管理 14、credwiz:备份或还原储存的用户名和密码 15、comexp.msc:打开系统组件服务 16、control:控制面版 17、dcomcnfg:打开系统组件服务 18、Dccw:显示颜色校准 19、devmgmt.msc:设备管理器 20、desk.cpl:屏幕辨别率 21、dfrgui:优化驱动器 Win 7→dfrg.msc:磁盘碎片整理程序 22、dialer:电话拨号程序 23、diskmgmt.msc:磁盘管理 24、dvdplay:DVD播放器 25、dxdiag:检查DirectX信息 26、eudcedit:造字程序 27、eventvwr:事件查看器 28、explorer:打开资源管理器 29、Firewall.cpl:Win防火墙 30、FXSCOVER:传真封面编辑器 31、fsmgmt.msc:共享文件夹管理器 32、gpedit.msc:组策略 33、hdwwiz.cpl:设备管理器 34、inetcpl.cpl:Internet属性 35、intl.cpl:区域 36、iexpress:木马捆绑工具,系统自带 37、joy.cpl:游戏控制器 38、logoff:注销命令 39、lusrmgr.msc:本地用户和组 40、lpksetup:语言包安装/删除向导,安装向导会提示下载语言包 41、lusrmgr.msc:本机用户和组 42、main.cpl:鼠标属性 43、mmsys.cpl:声音 44、magnify:放大……

    SE_Gai 2024-12-12
    9 0 0
  • 【Linux】匿名管道通信场景——进程池

    1. 初始化进程池 进程池的实现是依靠匿名管道,通过进程间通信使得父进程能够管理多个进程任务,相当于父进程拥有了很多个进程——进程池,通过不同的进程完成指定的任务。 所以我们需要创建多个匿名管道和子进程,进行进程间通信,发送信息给子进程让它们根据接收到的信息处理相关任务。 因为有多个管道和子进程,为了方便父进程使用不同管道发送对应信息给子进程,我们需要将管道的文件描述符以及对应子进程的pid保存起来,我们选择将它们封装在一个Channel类中。又因为有多个匿名管道和子进程,所以将多个Channel类对象储存在C++STL中的容器vector中来方便父进程进行管理进程池。 代码如下: int InitProcesspool(int num,std::vector<Channel>& channels) { for(int i = 0; i < num; i++)//使用循环创建多个匿名管道和子进程 { //1.创建匿名管道 int pipefd[2] = {0}; int n = pipe(pipefd); if(n < 0) return 2;//根据不同的返回值判断原因,也可以使用枚举来约定返回值代表的内容 //2.创建子进程 pid_t id = fork(); if(id < 0) return 3; //3.建立通信管道,父子进程关闭读端或写端 if(id == 0)//子进程 { //子进程读取,关闭写端 ::close(pipefd[1]); //dup2 dup2(pipefd[0],0); //子进程需要执行的内容 Work(); ::exit(0); } //父进程 //父进程写入,关闭读端 ::close(pipefd[0]); channels.emplace_back(pipefd[1],id);//保存在channel对象中并存入vector } return 0; } 对子进程内部,我们使用dup2系统调用将匿名管道读端文件描述符与标准输入stdin交换,这样我们就不需要保存不同进程对应匿名管道的读端文件描述符,只需要统一从0号文件描述符中读取内容即可。 对于Channel类: class Channel{ public: Channel(int fd,pid_t who):_fd(fd),_who(who) { _name = "Channel-"+std::to……

    SE_Wang 2024-12-11
    27 0 0
  • CloudOS 云操作系统架构

    伴随信息化技术的飞跃发展,传统数据中心管理中存在资源瓶颈、信息孤岛、标准不一、系统复杂、服务水平低下等诸多矛盾被愈发激化,IT的整体管控模式亟需向云化模式转型。 H3C CloudOS云操作系统作为全栈式云平台,聚合AI、大数据、IoT等多种技术能力及百态行业云场景化能力,借助强大算力与海量存储,依托数据智能分析手段,帮助用户在复杂且多样的IT环境中及时交付出色的应用程序和功能,并为容器化、微服务等重要IT举措提供支持,助力百行百业用户实现数字化转型。

    SE_Gai 2024-12-11
    8 0 0
  • Linux之网络编程(UDP)

    第1关:UDP套接字创建与端口绑定 #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <errno.h> #include <string.h> /************************ * port: 需要绑定的端口号 * 返回值: 调用成功返回0,否则返回-1 *************************/ int UDPSocket(unsigned short port) { int ret = -1; /********** BEGIN **********/ int sockfd; struct sockaddr_in server_addr; // 创建UDP套接字 sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { printf("创建UDP套接字失败: %s\n", strerror(errno)); return -1; } // 初始化服务器地址结构体 memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = htonl(INADDR_ANY); server_addr.sin_port = htons(port); // 绑定端口 ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (ret == -1) { printf("绑定端口失败: %s\n", strerror(errno)); close(sockfd); return -1; } ret = 0; /********** END **********/ return ret; } 第2关:UDP数据传送 #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #define PORT 8888 int main() { int sockfd; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd == -1) { return -1; } struct sockaddr_in addr; bzero(&addr, sizeof(addr)); //清空 addr.sin_family = AF_INET; addr.sin_port = htons(PORT); addr.sin_addr.s_addr = htonl(INADDR_ANY); //与PO……

    SE_Wang 2024-12-10
    6 0 0
  • 安装流程

    图3-1 交换机安装流程图 安装前的确认 • 您已经仔细阅读第 2 章内容。 • 第 2 章中所述的要求已经满足。 • 交换机发货时会随机附带装箱清单,请您根据装箱清单中的项目列表确认发货附件是否齐全、 完好。如果存在损坏或遗失,请及时联系代理商或当地技术支持人员进行更换。 开始安装 将交换机安装到机柜 交换机接地 安装结束 安装电源系统 安装风扇框 连接电源线 安装后检查 确定安装场所 将交换机安装到工作台 安装单板 安装后挡风板(可选) 安装机箱扩展走线架(可选) 安装机箱防尘网(可选) 3-3 如果您想了解安全规范以及兼容信息,请参见 H3C S12500 Series Routing Switches Installation Guide “Regulatory Compliance and Safety Information”。

    SE_Gai 2024-12-10
    3 0 0