Loading

网易互娱C++游戏引擎研发工程师面经

1.CPU频率是什么

CPU频率,也称为CPU时钟频率或主频,表示CPU每秒钟完成的时钟周期数,单位是Hz。
主频 = 外频 × 倍频:外频是CPU与主板同步运行的基准频率,倍频是主频与外频的比值。通过调整两者可提升主频,但现代CPU的倍频通常被锁定。

2.指令是什么,指令集是什么,指令和时钟周期的关系

指令(Instruction)是计算机程序中的基本命令,用于指示CPU执行特定操作(如加法、数据传输等)。每条指令包含两部分:操作码(指定操作类型(如ADD、MOV))和操作数(提供操作所需的数据或地址)。
指令集(Instruction Set Architecture, ISA)是CPU能理解和执行的所有指令的集合,主要分为两类:CISC(复杂指令集):单条指令可完成复杂操作(如x86架构),但执行需多个时钟周期。RISC(精简指令集):指令简单且单周期执行(如ARM、RISC-V)。
简单指令(如寄存器加法)可能只需1个时钟周期。
复杂指令(如乘法)可能需要多个时钟周期,甚至通过流水线分阶段完成(取指、译码、执行等)

3.内存频率指什么,和CPU频率有什么关系

内存频率(Memory Frequency)是指内存模块每秒钟能完成的时钟周期数。等效频率:因DDR(双倍数据速率)技术,内存可在时钟信号的上升沿和下降沿各传输一次数据,因此:
DDR:等效频率 = 工作频率 × 2(如DDR4 3200MHz的等效频率为3200MHz,实际工作频率为1600MHz)。
DDR5:通过更高效的设计,等效频率可达工作频率的4倍
CPU外频与内存频率:传统CPU通过外频(Base Clock)与内存交互。内存频率需与CPU外频匹配,否则系统会自动降频或通过分频机制协调。

3.1.存储器的层次结构介绍一下

寄存器(Registers):位于CPU内部,速度最快(1个时钟周期访问),容量最小(通常为KB级),直接参与运算。
高速缓存(Cache):
L1 Cache:分指令缓存(I-Cache)和数据缓存(D-Cache),容量约几十KB,访问延迟约1-3个周期。
L2 Cache:容量几百KB至几MB,延迟约10-20周期。
L3 Cache:共享缓存,容量数MB至数十MB,延迟约30-50周期。
主存(DRAM):容量GB级,访问延迟约100-300周期,CPU直接寻址。
辅存(外存):如SSD/HDD,容量TB级,访问延迟毫秒级,需通过I/O接口与CPU交互。

3.2.CPU中的几级缓存的作用

1.一级缓存(L1 Cache)
作用:最接近CPU核心,存储CPU当前最急需的指令和数据,分为两部分:
指令缓存(I-Cache):暂存即将执行的指令(如ADD、MOV)。
数据缓存(D-Cache):存储操作数(如变量、计算结果)。
特点:
速度最快(1-3个时钟周期访问),容量最小(通常32KB-256KB)。
采用静态RAM(SRAM),与CPU同频运行,命中率约80%。
Intel部分CPU(如Pentium 4)用追踪缓存(T-Cache)替代指令缓存,直接存储解码后的微指令(μOps)。
2.二级缓存(L2 Cache)
作用:作为L1的备用库,存储CPU可能下一步需要的数据,减少访问主存延迟。
特点:
速度稍慢(10-20周期),容量较大(256KB-8MB)。
现代CPU将L2集成于核心内,共享或独占设计(多核CPU通常每核独占L2)。
命中率约80%(即L1未命中的20%数据中,80%可在L2找到)。
3.三级缓存(L3 Cache)
作用:多核共享的缓存,协调不同核心间的数据一致性,减少访问主存频率。
特点:
速度最慢(30-50周期),容量最大(4MB-50MB+)。
在服务器/高端CPU中作用显著,可降低内存延迟约5%(仅5%数据需从主存读取)。

工作原理:局部性优化:利用时间局部性(重复访问)和空间局部性(邻近访问),缓存热点数据,整体命中率可达90%

4.脏cache是什么,如何处理

脏Cache是指缓存中的数据已被修改,但尚未同步到更低层存储(如主存或磁盘)的状态。它是写回策略(Write-back)的产物:在写回模式下,CPU修改缓存数据后不会立即写回主存,而是将修改后的缓存行标记为“脏”(Dirty),待后续触发条件(如缓存行被替换)时再同步。
脏Cache的处理方法:缓存一致性协议(如MESI):通过状态机(Modified/Exclusive/Shared/Invalid)管理脏数据:
写回时机:当脏缓存行被替换(Eviction)时,必须写回主存。
多核同步:其他核心访问脏数据时,通过总线嗅探(Bus Snooping)触发写回或共享。

5.如何通过C++程序判断机器是大端机器还是小端机器,Union使用过没有

方法1:指针法

    int num = 0x12345678;
    char *ptr = reinterpret_cast<char*>(&num);  // 将int指针转为char指针
    if (*ptr == 0x78) {
        std::cout << "小端 (Little Endian)\n";
    }
    else if (*ptr == 0x12) {
        std::cout << "大端 (Big Endian)\n";
    }

方法2:联合体(Union)法

union EndianTest {
    uint32_t num;
    char bytes[4];
};
int main() {
    EndianTest test;
    test.num = 0x12345678;
    if (test.bytes[0] == 0x78) {
        std::cout << "小端模式 (Little Endian)\n";
    } else if (test.bytes[0] == 0x12) {
        std::cout << "大端模式 (Big Endian)\n";
    }
    return 0;
}

6.C++强制类型转换分别是什么,并介绍用途

C++四种命名强制转换:

double d = 3.14;
int a = static_cast<int>(d);  // 显式转换为int

static_cast(常规类型转换):基本数据类型转换(如int ↔ double)、父子类指针/引用的向上转型(派生类→基类)。

int num = 0x12345678;
char* ptr = reinterpret_cast<char*>(&num);  // 将int指针转为char指针

reinterpret_cast(低层重新解释):指针类型间的转换(如int* → char*)、函数指针类型转换(需谨慎使用)。

const int x = 10;
int* p = const_cast<int*>(&x);  // 去除const属性
*p = 20;  // 修改原const变量(行为未定义,慎用!)

const_cast(去除const属性):修改const或volatile修饰的变量(通常用于兼容旧代码)。

class Base { virtual void foo() {} };
class Derived : public Base {};
Base* b = new Derived;
Derived* d = dynamic_cast<Derived*>(b);  // 安全向下转型

dynamic_cast(多态类型安全转换):多态类型(含虚函数)的向下转型(派生类←基类)。

7.平时写哪些算法题?给一个vector<int>,递归实现快排

// 分区函数(以首元素为基准)
int Partition(vector<int>& nums, int left, int right) {
    int pivot = nums[left];  // 选择第一个元素作为基准
    while (left < right) {
        // 从右向左找第一个小于基准的元素
        while (left < right && nums[right] >= pivot) right--;
        nums[left] = nums[right];  // 将小元素放到左侧
        // 从左向右找第一个大于基准的元素
        while (left < right && nums[left] <= pivot) left++;
        nums[right] = nums[left];  // 将大元素放到右侧
    }
    nums[left] = pivot;  // 基准归位
    return left;
}

// 递归快速排序主函数
void QuickSort(vector<int>& nums, int left, int right) {
    if (left >= right) return;  // 递归终止条件
    int pivot_pos = Partition(nums, left, right);
    QuickSort(nums, left, pivot_pos - 1);  // 递归排序左半部分
    QuickSort(nums, pivot_pos + 1, right);  // 递归排序右半部分
}
7.1.快排最差的情况有几层递归?

N层

7.2.如果分区点每次选中间,什么样的数据会导致最差的情况发生?举例说明

周期序列(锯齿形分布,如 [1, 3, 5, 7, 2, 4, 6, 8]):
数据呈周期性波动,且中间位置的值始终是当前子数组的最大值或最小值。
原因:每次分区后,中间值将子数组分为一个极小的子数组(长度≈1)和一个几乎包含剩余所有元素的子数组,递归深度接近 n。
特殊构造的“峰谷”序列:
数据交替出现峰值和谷值,且中间位置恰好是全局极值点。
原因:中间值无法有效分割数据,导致分区后子数组大小比例严重失衡。
全相同元素(退化特例):
所有元素值相同(如 [5,5,5,5])。
原因:无论选择哪个元素作为枢轴,分区结果均为一个空子数组和一个长度为 n−1 的子数组。

8.如何用不递归的方式实现递归

可以使用栈(Stack)来模拟,每次递归调用时,将当前状态(参数、局部变量等)压入栈中;返回时从栈中弹出状态并恢复。

9.Linux查看当前路径下的所有文件名的命令是什么

一、文件与目录操作
基础导航
pwd:显示当前路径
cd [目录]:切换目录(cd ~返回家目录,cd -返回上一路径)
ls [选项]:列出目录内容
-l:详细列表(权限/所有者/大小)
-a:显示隐藏文件(如.bashrc)
-h:人性化显示文件大小(如KB/MB)
文件管理
cp [选项] 源文件 目标:复制文件(-r递归复制目录)
mv 源文件 目标:移动/重命名文件
rm [选项] 文件:删除文件(-rf递归强制删除目录)
touch 文件名:创建空文件或更新时间戳
目录操作
mkdir [选项] 目录名:创建目录(-p创建多级目录,如mkdir -p a/b/c)
rmdir 目录名:删除空目录
文件查找
find /路径 -name "*.txt":按名称搜索文件
locate 文件名:通过数据库快速查找(需先运行updatedb)

二、文本处理
查看与编辑
cat 文件:显示全部内容
less/more 文件:分页查看(支持搜索,按q退出)
head -n 5 文件:显示前5行
tail -f 日志文件:实时追踪日志更新
文本分析
grep "关键词" 文件:过滤包含关键词的行(-i忽略大小写)
wc 文件:统计行数/单词数/字符数
sort 文件:按行排序(-r倒序)

三、系统信息与管理
硬件与状态
uname -a:显示内核版本/主机名
df -h:查看磁盘剩余空间
free -h:显示内存使用情况
top或htop:实时进程监控(CPU/内存占用)
用户与权限
chmod 755 文件:修改权限(7=rwx,5=r-x)
chown 用户:组 文件:更改所有者
sudo 命令:以管理员身份运行
服务管理
systemctl start/stop 服务名:控制服务(如nginx)
journalctl -u 服务名:查看服务日志

四、网络与通信
连接配置
ip a:查看IP地址(替代旧版ifconfig)
ping 域名/IP:测试网络连通性
ss -tuln:列出所有监听端口
远程操作
ssh 用户@IP:远程登录
scp 本地文件 用户@IP:远程路径:安全传输文件

五、软件管理
Debian/Ubuntu:
sudo apt update # 更新软件列表
sudo apt install 包名 # 安装软件
sudo apt remove 包名 # 卸载

10.Linux的文件权限有哪些

权限类型:可读(r)、可写(w)、可执行(x)。
权限分配对象:所有者(User)、所属组(Group)、其他用户(Others)。

11.Linux中chmod 777命令中777是什么意思

权限用二进制码表示,7=4+2+1,也就是三个权限都有,777表示三个分配对象都有全部的文件权限。
更安全的替代方案如755(所有者rwx,其他用户r-x)或644(所有者rw-,其他用户r--)。

12.内核态和用户态是什么,编译过Linux系统吗

内核态(Kernel Mode)和用户态(User Mode)是操作系统中两种不同的CPU运行级别,用于区分程序执行的权限和资源访问能力。
用户态:应用程序运行的非特权状态,只能访问受限的内存和资源,无法直接操作硬件或内核数据。需通过系统调用请求内核服务。
内核态:操作系统内核运行的特权状态,可访问所有内存、硬件和执行特权指令(如I/O操作、进程调度等),直接管理系统资源。

13.进程是什么

进程(Process)是计算机中已运行的程序实例,具有生命周期(创建、运行、终止)。每个进程拥有独立的地址空间和系统资源(如CPU寄存器、内存、文件句柄等)。多个进程可同时存在于内存中,由操作系统调度交替执行。进程由程序代码、数据集合和进程控制块(PCB)组成,PCB记录进程状态(运行、就绪、阻塞等)、优先级等信息。
进程与线程:进程是线程的容器,一个进程可包含多个线程。线程是CPU调度的基本单位,共享进程的资源。

13.1.进程的中断的底层实现以及进程为什么要中断

一、底层实现
硬件级流程
中断触发:外部设备(如键盘、磁盘)通过CPU引脚(如INTR/NMI)发送信号,或内部事件(如除零、缺页)触发中断。
状态保存:CPU暂停当前指令,自动保存程序计数器(PC)、程序状态字(PSW)等寄存器到内核栈,并关闭中断(清除IF标志)。
中断处理:通过中断向量表(IDT)跳转到对应的中断服务程序(ISR),执行设备驱动或异常处理逻辑。
恢复执行:ISR完成后,通过IRET指令恢复现场,重新开放中断并返回原程序。
操作系统级流程
上下文切换:内核保存进程的CPU环境(如通用寄存器、内存页表)到进程控制块(PCB),切换到中断处理进程。
优先级调度:高优先级中断可嵌套低优先级中断,确保紧急事件优先处理。
二、中断的原因
实时响应:允许CPU立即处理紧急事件(如硬件故障、用户输入),避免轮询等待。
资源高效利用:在I/O等待期间切换进程,提高CPU利用率(如磁盘读写时执行其他任务)。
多任务协调:通过时间片中断强制进程切换,实现公平调度。
错误隔离:异常中断(如非法指令)可终止错误进程,保护系统稳定性。

14.虚拟内存到物理内存是如何映射的

虚拟内存到物理内存的映射是通过页表(Page Table)和内存管理单元(MMU)共同实现的。
虚拟地址分为两部分:页号(Page Number)和页内偏移量(Offset)。物理内存也被划分为相同大小的页框(Frame)。
操作系统为每个进程维护一个页表,记录虚拟页号到物理页框号的映射关系。
CPU访问虚拟地址时,MMU提取虚拟页号。通过页表找到对应的物理页框号。若页表项有效(已调入内存),则结合偏移量生成物理地址。
转换后援缓冲器(TLB)缓存常用页表项,若命中(TLB hit)则直接获取物理地址;未命中(TLB miss)需访问内存中的页表。
若页表项无效(页面未调入内存),触发缺页中断。操作系统将所需页面从磁盘(交换空间或文件)加载到物理内存,更新页表后重新执行指令。

优化:
多级页表:减少页表内存占用(如x86使用四级页表)。
当物理内存不足时,选择不活跃页面换出到磁盘(如LRU算法)。
多个进程可映射同一物理页(如动态库代码),减少冗余。

15.页表是什么

页表结构:
页表项(PTE):每个表项包含:物理页框号:虚拟页对应的物理内存块号。控制位:如存在位(P)、读写权限位(R/W)、修改位(D)等,用于内存保护和状态管理。
多级页表:针对大地址空间(如64位系统),采用多级页表(如二级、四级)减少内存占用。

16.socket的API有哪些,connect和listen哪个是服务端哪个是客户端

基础操作
socket():创建套接字
close():关闭套接字
地址绑定与连接
bind():将套接字与本地地址绑定(服务端)
connect():客户端向服务器发起连接请求
listen():服务端设置监听队列等待连接
accept():服务端接受客户端连接
数据传输
send()/recv():面向连接(如TCP)的数据收发
sendto()/recvfrom():无连接(如UDP)的数据收发
辅助功能
gethostbyname():域名解析
setsockopt()/getsockopt():设置/获取套接字选项
典型调用流程:
服务端:socket() → bind() → listen() → accept()
客户端:socket() → connect()

17.介绍TCP/IP和UDP

TCP/IP(Transmission Control Protocol/Internet Protocol)是一组用于互联网通信的协议集合,它定义了数据如何在网络中传输。TCP/IP协议族分为四层:
应用层:负责处理特定的应用程序细节,如HTTP、FTP等。
传输层:提供端到端的通信服务,主要协议是TCP和UDP。
网络层:负责数据包的路由和转发,核心协议是IP。
链路层:处理物理网络连接,如以太网。

TCP(传输控制协议)是TCP/IP协议族中的核心协议之一,它提供面向连接、可靠的字节流服务。TCP通过以下机制确保数据传输的可靠性:
三次握手建立连接。
数据包确认和超时重传机制。
流量控制和拥塞控制。
TCP适用于需要高可靠性的应用,如网页浏览(HTTP)、文件传输(FTP)等

UDP(User Datagram Protocol,用户数据报协议)是另一种传输层协议,与TCP不同,UDP是无连接且不可靠的。它的特点包括:
无连接:不需要预先建立连接,直接发送数据。
不可靠:不保证数据包的顺序、丢失或重复。
高效:由于没有复杂的控制机制,UDP的开销更小,传输速度更快。
UDP适用于实时性要求高、能容忍少量数据丢失的应用,如:视频流媒体(如在线视频)、语音通话(VoIP)和DNS查询等。

posted @ 2025-04-03 11:51  C_noized  阅读(25)  评论(0)    收藏  举报