锐势信息的面试

预处理,编译,汇编,链接

c++11新特性

Lambda 表达式

右值引用和移动语义

初始化列表

线程库

范围for ,auto, 智能指针,nullptr

epoll的两种工作模式

水平触发(Level Triggered,LT)

原理:
水平触发是 epoll 的默认工作模式。在这种模式下,只要文件描述符对应的 I/O 条件满足(例如,有数据可读或者可写),epoll_wait 就会一直返回该文件描述符,直到该条件不再满足。也就是说,只要缓冲区中有数据,就会一直触发事件。

边缘触发(Edge Triggered,ET)

原理:

边缘触发是一种更为高效的工作模式。在这种模式下,只有当文件描述符的 I/O 条件发生变化(例如,从无数据变为有数据,或者从不可写变为可写)时,epoll_wait 才会返回该文件描述符。也就是说,只有在数据状态发生变化的 "边缘" 时刻才会触发事件。

举一些一直在运行的linux上的进程

  1. systemd
    • 是 Linux 系统中最新的初始化系统 ,它负责系统启动和管理系统服务 等。它作为系统的第一个进程,PID(进程 ID)通常为 1,会一直运行并启动其他所有进程,管理系统的各个方面,如服务的启动、停止、重启,以及系统资源的分配和管理等。
  2. kthreadd
    • 内核线程的管理进程,负责创建和管理其他内核线程,这些内核线程用于执行各种内核任务,如内存管理、进程调度、设备驱动等。它一直运行,为内核提供必要的线程支持,确保系统的核心功能正常运行。
  3. rcu_sched
    • 是 Linux 内核中的 RCU(Read-Copy Update)机制的一部分,主要用于实现对共享数据结构的无锁访问,以提高系统的并发性能。它在系统运行期间持续运行,负责协调和管理 RCU 相关的操作,确保数据的一致性和系统的高效运行。
  4. sshd
    • 是 SSH(Secure Shell)服务器进程,用于提供远程安全登录和命令执行等服务。如果系统开启了 SSH 服务,sshd 进程会一直运行,监听指定的端口,等待远程客户端的连接请求,并处理客户端的登录和命令执行等操作,方便用户通过 SSH 协议远程管理系统。
  5. httpd
    • 是常用的 Web 服务器软件 Apache 的主进程,用于处理 HTTP 请求,提供 Web 服务。如果系统部署了 Web 应用,httpd 进程会一直运行,监听 80 端口(默认)或其他指定端口,接收和处理来自客户端的 HTTP 请求,将相应的网页内容返回给客户端。
  6. mysqld
    • 是 MySQL 数据库服务器的主进程,负责管理和维护 MySQL 数据库。当系统安装并运行了 MySQL 数据库时,mysqld 进程会一直运行,监听指定的端口,接受客户端的连接请求,处理数据库的读写操作,管理数据库的事务、存储等功能。
  7. crond
    • 是 Linux 系统中的定时任务调度进程,用于定期执行用户或系统设置的定时任务(crontab 任务)。它一直在后台运行,按照设定的时间间隔检查并执行相应的任务,比如定时备份数据、清理日志、发送定时邮件等。
  8. 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 锁的种类及原理

  1. 自旋锁(Spinlock)

    通过原子操作(如test-and-set)实现,未获取锁时线程忙等待,适用于短临界区。内核中通过spin_lock()实现,依赖底层原子指令(如x86的lock cmpxchg)。

  2. 互斥锁(Mutex)

    基于内核的futex(快速用户态互斥锁),未获取锁时线程休眠。内核态实现依赖信号量和等待队列,用户态通过pthread_mutex_t封装。

  3. 读写锁(rwlock)

    通过原子变量区分读写状态,读共享、写独占。内核中rwlock_t使用自旋锁保护计数器,用户态pthread_rwlock_t结合条件变量实现。

  4. RCU(Read-Copy-Update)

    无锁读,写操作通过副本替换和延迟释放旧数据实现同步。依赖内存屏障和原子指针操作。


C++ 锁的种类及原理

  1. std::mutex

    底层通常封装pthread_mutex_t,基于操作系统的互斥锁(如Linux的futex),通过原子操作和内核等待队列实现阻塞。

  2. std::recursive_mutex

    允许同一线程重复加锁,内部记录持有线程ID和计数器,释放需匹配加锁次数。

  3. std::shared_mutex(C++17)

    读写锁实现,用户态通过原子变量和条件变量区分读写模式,类似pthread_rwlock_t

  4. std::timed_mutex

    支持超时加锁,底层通过系统调用(如pthread_mutex_timedlock)实现时间判断。

递归锁(Recursive Lock std::recursive_mutex

递归锁是一种允许同一线程多次加锁的特殊互斥锁,主要用于解决嵌套调用场景中的死锁问题。


核心特性
  1. 重入性

    同一线程可重复加锁,内部通过计数器记录加锁次数,每次解锁计数器减1,直到归零时真正释放锁。
    底层实现 :记录持有线程ID和计数器(如C++的std::recursive_mutex)。

  2. 避免自死锁

    普通互斥锁(如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,断点续传。

相关推荐
晴殇i1 小时前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
绝无仅有2 小时前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
绝无仅有2 小时前
Redis大Key问题排查与解决方案全解析
后端·面试·架构
AAA梅狸猫3 小时前
Looper.loop() 循环机制
面试
AAA梅狸猫3 小时前
Handler基本概念
面试
Wect3 小时前
浏览器缓存机制
前端·面试·浏览器
掘金安东尼4 小时前
Fun with TypeScript Generics:玩转 TS 泛型
前端·javascript·面试
掘金安东尼4 小时前
Next.js 企业级落地
前端·javascript·面试
掘金安东尼4 小时前
React 性能优化完全指南 2026
前端·javascript·面试
掘金安东尼15 小时前
让 JavaScript 更容易「善后」的新能力
前端·javascript·面试