预处理,编译,汇编,链接
c++11新特性
Lambda 表达式
右值引用和移动语义
初始化列表
线程库
范围for ,auto, 智能指针,nullptr
epoll的两种工作模式
水平触发(Level Triggered,LT)
原理:
水平触发是 epoll
的默认工作模式。在这种模式下,只要文件描述符对应的 I/O 条件满足(例如,有数据可读或者可写),epoll_wait
就会一直返回该文件描述符,直到该条件不再满足。也就是说,只要缓冲区中有数据,就会一直触发事件。
边缘触发(Edge Triggered,ET)
原理:
边缘触发是一种更为高效的工作模式。在这种模式下,只有当文件描述符的 I/O 条件发生变化(例如,从无数据变为有数据,或者从不可写变为可写)时,epoll_wait
才会返回该文件描述符。也就是说,只有在数据状态发生变化的 "边缘" 时刻才会触发事件。
举一些一直在运行的linux上的进程
- systemd
- 是 Linux 系统中最新的初始化系统 ,它负责系统启动和管理系统服务 等。它作为系统的第一个进程,PID(进程 ID)通常为 1,会一直运行并启动其他所有进程,管理系统的各个方面,如服务的启动、停止、重启,以及系统资源的分配和管理等。
- kthreadd
- 是内核线程的管理进程,负责创建和管理其他内核线程,这些内核线程用于执行各种内核任务,如内存管理、进程调度、设备驱动等。它一直运行,为内核提供必要的线程支持,确保系统的核心功能正常运行。
- rcu_sched
- 是 Linux 内核中的 RCU(Read-Copy Update)机制的一部分,主要用于实现对共享数据结构的无锁访问,以提高系统的并发性能。它在系统运行期间持续运行,负责协调和管理 RCU 相关的操作,确保数据的一致性和系统的高效运行。
- sshd
- 是 SSH(Secure Shell)服务器进程,用于提供远程安全登录和命令执行等服务。如果系统开启了 SSH 服务,sshd 进程会一直运行,监听指定的端口,等待远程客户端的连接请求,并处理客户端的登录和命令执行等操作,方便用户通过 SSH 协议远程管理系统。
- httpd
- 是常用的 Web 服务器软件 Apache 的主进程,用于处理 HTTP 请求,提供 Web 服务。如果系统部署了 Web 应用,httpd 进程会一直运行,监听 80 端口(默认)或其他指定端口,接收和处理来自客户端的 HTTP 请求,将相应的网页内容返回给客户端。
- mysqld
- 是 MySQL 数据库服务器的主进程,负责管理和维护 MySQL 数据库。当系统安装并运行了 MySQL 数据库时,mysqld 进程会一直运行,监听指定的端口,接受客户端的连接请求,处理数据库的读写操作,管理数据库的事务、存储等功能。
- crond
- 是 Linux 系统中的定时任务调度进程,用于定期执行用户或系统设置的定时任务(crontab 任务)。它一直在后台运行,按照设定的时间间隔检查并执行相应的任务,比如定时备份数据、清理日志、发送定时邮件等。
- NetworkManager
- 用于管理系统的网络连接,自动检测和配置网络接口,支持多种网络连接方式,如有线、无线、VPN 等。它在系统运行期间持续运行,监控网络状态的变化,自动进行网络连接的切换和配置,确保系统能够正常连接到网络。
git rebase
git merge
:会创建一个新的合并提交,将两个分支的历史合并在一起,提交历史会呈现出分叉的结构,能清晰展示分支的合并情况。git rebase
:将一个分支的提交按顺序应用到另一个分支上,使提交历史保持线性,更加简洁直观,但可能会改变提交的哈希值。
linux查看CPU的占用情况
top 命令 各个进程的资源使用情况,包括 CPU 占用率。占用率(us
)、内核空间占用率(sy
)、空闲率(id)
htop 命令 top
命令的增强版,提供了更直观、更丰富的界面,支持鼠标操作。
vmstat 1命令 虚拟机使用 每一秒更新信息
mpstat 命令 多核心CPU
top示例
其他占比相关信息
-
%CPU:表示进程占用 CPU 的百分比。该数值反映了进程在 CPU 资源分配中所占的份额,百分比越高,说明该进程对 CPU 的使用越频繁。例如,如果一个进程的 % CPU 值为 50%,意味着在统计的时间间隔内,该进程占用了 CPU 一半的运算资源。
-
us(用户空间 CPU 使用率):显示了用户进程占用 CPU 的时间百分比。通常是应用程序、命令等在用户态下运行所占用的 CPU 时间比例。
-
sy(系统空间 CPU 使用率):代表系统内核进程占用 CPU 的时间百分比。包括内核态下的系统服务、中断处理等操作所占用的 CPU 时间。
-
ni(低优先级用户进程 CPU 使用率):表示以较低优先级运行的用户进程占用 CPU 的时间百分比。这些进程的优先级相对较低,在系统资源紧张时,可能会被优先抢占 CPU 资源。
-
id(空闲 CPU 时间百分比):显示 CPU 处于空闲状态的时间百分比。该值越高,说明系统的 CPU 资源越充裕,反之则表示 CPU 负载较高。
-
wa(等待 I/O 的 CPU 时间百分比):表示 CPU 等待 I/O 操作完成所花费的时间百分比。如果这个值较高,通常意味着系统存在 I/O 瓶颈,例如硬盘读写速度慢、网络延迟高等问题,导致 CPU 需要等待 I/O 操作完成才能继续执行其他任务。
-
%MEM:指进程占用物理内存的百分比。它体现了进程在系统内存资源分配中所占用的份额。比如,一个进程的 % MEM 为 20%,表示它占用了系统 20% 的可用物理内存。
-
VIRT(虚拟内存大小):进程使用的虚拟内存总量,包括所有代码、数据和共享库占用的空间,以及可能尚未实际分配物理内存的部分。
-
RES(常驻内存大小):进程实际占用的物理内存大小,即进程当前在内存中驻留的部分,不包括已经换出到磁盘交换空间(swap)的内存。
-
SHR(共享内存大小):进程使用的共享内存大小,这部分内存可以被多个进程共享,用于进程间通信或共享数据。
-
PR(优先级):表示进程的优先级,数值越小优先级越高。优先级高的进程在竞争 CPU 和内存等资源时会更有优势。
-
NI(谦让度):用于调整进程的优先级,范围通常是 - 20 到 19,-20 表示最高优先级,19 表示最低优先级。用户可以通过调整 NI 值来改变进程获取 CPU 资源的优先级。
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1211 root 20 0 392564 56088 15984 S 1.0 5.6 0:01.50 Xorg
3172 root 20 0 659796 24200 17252 S 0.7 2.4 0:00.49 gnome-term+
智能指针循环引用的问题
但当两个或多个 std::shared_ptr
相互引用,形成一个循环时,引用计数永远不会变为 0,导致对象无法被销毁,从而造成内存泄漏。
std::weak_ptr
是一种弱引用的智能指针,它不会增加对象的引用计数,因此不会影响对象的生命周期。可以将循环引用中的一个 std::shared_ptr
替换为 std::weak_ptr
来打破循环。
虚函数和纯虚函数有什么区别
虚函数主要用于实现运行时多态。当通过基类指针或引用调用虚函数时,会根据指针或引用实际指向的对象类型来决定调用哪个版本的函数,这种机制称为动态绑定。
纯虚函数的主要作用是定义一个接口规范,要求派生类必须实现该函数。抽象类不能实例化对象,它的主要用途是作为基类,为派生类提供一个统一的接口,派生类必须实现抽象类中的所有纯虚函数,否则该派生类也会成为抽象类。
c++中有线程安全的容器吗
没有的
如果线程安全你会怎么解决
互斥锁,读写锁,原子操作,避免共享数据
锁的种类,底层实现机制
Linux 锁的种类及原理
-
自旋锁(Spinlock)
通过原子操作(如
test-and-set
)实现,未获取锁时线程忙等待,适用于短临界区。内核中通过spin_lock()
实现,依赖底层原子指令(如x86的lock cmpxchg
)。 -
互斥锁(Mutex)
基于内核的
futex
(快速用户态互斥锁),未获取锁时线程休眠。内核态实现依赖信号量和等待队列,用户态通过pthread_mutex_t
封装。 -
读写锁(rwlock)
通过原子变量区分读写状态,读共享、写独占。内核中
rwlock_t
使用自旋锁保护计数器,用户态pthread_rwlock_t
结合条件变量实现。 -
RCU(Read-Copy-Update)
无锁读,写操作通过副本替换和延迟释放旧数据实现同步。依赖内存屏障和原子指针操作。
C++ 锁的种类及原理
-
std::mutex
底层通常封装
pthread_mutex_t
,基于操作系统的互斥锁(如Linux的futex
),通过原子操作和内核等待队列实现阻塞。 -
std::recursive_mutex
允许同一线程重复加锁,内部记录持有线程ID和计数器,释放需匹配加锁次数。
-
std::shared_mutex(C++17)
读写锁实现,用户态通过原子变量和条件变量区分读写模式,类似
pthread_rwlock_t
。 -
std::timed_mutex
支持超时加锁,底层通过系统调用(如
pthread_mutex_timedlock
)实现时间判断。
递归锁(Recursive Lock std::recursive_mutex)
递归锁是一种允许同一线程多次加锁的特殊互斥锁,主要用于解决嵌套调用场景中的死锁问题。
核心特性
-
重入性
同一线程可重复加锁,内部通过计数器记录加锁次数,每次解锁计数器减1,直到归零时真正释放锁。
底层实现 :记录持有线程ID和计数器(如C++的std::recursive_mutex
)。 -
避免自死锁
普通互斥锁(如
std::mutex
)若同一线程重复加锁会直接死锁,递归锁则允许这种嵌套操作。
典型使用场景
- 递归函数:函数内部调用自身时需重复加锁。
- 多层级调用:多个函数嵌套调用且共享同一锁资源。
TCP和UDP
如果给你一个UDP你要怎么实现他的可靠
确认应答,超时重传
- 接收端缓冲排序:接收方维护缓冲区,按序列号重组乱序数据包后提交给应用层。
- 数据校验:除UDP头部校验和外,可添加应用层校验(如CRC32),确保内容未损坏
bool*类型可以和void*互相转换吗
任何指针类型都可以隐式转换为void*,所以bool*转void*是允许的。但反过来,void*转bool*需要显式转换,比如使用static_cast或者reinterpret_cast。不过,这样做可能有风险,因为如果void*原本不是指向bool类型,会导致未定义行为。
代码执行结果题
内存对齐,父类指针调用子类对象和子类对象初始化父类对象
double为8位,new返回的是一个指针,父类指针调用子类对象
如果使用父类指针指向子类对象,并且调用的是普通成员函数(非虚函数),那么调用的是父类中定义的该函数,而不是子类中重写的同名函数。这是因为普通成员函数的调用是在编译时进行静态绑定的,编译器根据指针的类型(即父类类型)来确定要调用的函数。(我是回答对了吧)。

野指针举个例子,问了nullptr是什么,c的指针和cpp的引用有什么区别,bool*类型可以和void*互相转换吗
任何指针类型都可以隐式转换为void*,所以bool*转void*是允许的。但反过来,void*转bool*需要显式转换,比如使用static_cast或者reinterpret_cast。不过,这样做可能有风险,因为如果void*原本不是指向bool类型,会导致未定义行为。
获得一个递增的的序列要怎么遍历二叉平衡搜索树
中序,知道是先遍历左再中再遍历右,不知道为什么说成前序了
c++中unordered_map底层哈希表是怎么处理哈希冲突的
链地址法的基本原理
链地址法的核心思想是,对于哈希表中的每个槽(bucket),它不仅仅存储一个元素,而是存储一个链表(或其他动态数据结构,如红黑树 )。当发生哈希冲突时,将新的元素插入到对应槽的链表中,(哈希桶采用红黑树里面也是可以的)
vector 和 deque,断点续传。