1.自我介绍就不多赘述了
2. 请介绍一下你的项目经历
- 介绍了专辑鉴赏项目,前端使用html语言编写,后端基于http协议使用C语言进行网页开发。此外,还提及项目中涉及处理多线程问题以及做过内存池管理项目。
3. 项目中HTTP协议是使用库实现的吗
- 真忘了,只能往别的地方掰扯,我说我记得HTTP底层是TCP协议,通过TCP建立连接,经过传输层、网络层找到服务器地址实现通信。
4. 实际开发过程中遇到过什么问题,如何解决的
- 将项目从Linux系统移植到云服务器时,网页无法打开。经查阅资料发现是80端口未打开,打开后网页得以正常显示。
5. 处理多线程问题需要注意什么
- 需要注意线程安全、资源竞争和死锁等问题。解决线程安全问题可使用锁保护共享资源;避免死锁要尽量避免多个锁嵌套使用、统一加锁顺序或使用超时锁;线程数太多时可使用线程池复用线程。
6. 进程申请的内存是虚拟内存还是物理内存,虚拟内存和物理内存如何映射
- 进程申请内存后拿到的是虚拟内存地址。虚拟内存是操作系统提供的假象内存空间,每个进程有独立的虚拟地址空间;物理内存是内存条上的存储单元,系统会调配物理内存给不同进程使用。
7. 在一台给定配置的电脑上,每个进程理论上可得的内存大小受哪些因素影响
- 受操作系统位数、系统总物理内存、交换空间、单个进程限制、地址空间布局以及分配方式等因素影响。
8. 32位系统中每个进程理论上可操作的内存空间最大是多少
- 32位系统中,理论上每个进程可操作的虚拟内存最大为4G。
9. 假设物理内存只有4G,有5个进程,每个进程启动时申请1G内存,操作系统会如何处理
- 操作系统会使用虚拟内存、分页机制和交换空间来解决。采用按需分配和页面置换策略,不会一次性给进程分配所有所需内存,而是先给活跃部分分配物理内存页,将不常用的内存页换到硬盘的交换空间,再把新需要的内存页从磁盘换进来。
10. 内存池前后添加强防止越界怎么理解,为什么要加
-在内存池前后添加强制边界,是指在内存池的起始和结束位置额外添加一些特殊标记(通常是设置特定的标记值)。在内存池_边界标识法中,通过在内存池的前后各添加一个标记单元,设置其tag
为 1 来表示边界。
Space pav = (Space)malloc((SIZE+2) * sizeof(WORD));// 内存池 + 2 边界
pav->tag = 1; // 左边界
pav++;
// ...
(p + 1)->tag = 1; // 右边界
原因:
-防止内存越界访问:在内存管理过程中,可能会出现程序意外地访问超出内存池范围的情况。例如,在合并相邻空闲块时,如果没有边界标记,可能会错误地访问到内存池之外的区域,导致未定义行为(如程序崩溃、数据损坏等)。通过添加边界标记,可以在程序访问到边界时进行检查,避免越界访问。
-简化合并逻辑:在释放内存时,需要判断相邻的内存块是否为空闲块,以便进行合并操作。边界标记可以作为一个明确的终止条件,简化合并逻辑,避免不必要的错误。
11. 在申请内存的函数中需要传什么参数,返回值是什么
(1)在伙伴系统中:
-参数:
FreeList* pf:指向空闲链表数组的指针,用于管理不同大小的空闲块。
int n:需要申请的内存块大小,以WORD_b
为单位。
-返回值:
如果申请成功,返回一个指向分配的内存块的指针WORD_b*
;
如果申请失败(如没有足够的空闲块),返回NULL
。
(2)在边界标识法中:
-参数:
Space* pav:指向内存池的指针,用于管理空闲内存块。
int n需要申请的内存块大小,以WORD
为单位。
-返回值:
如果申请成功,返回一个指向分配的内存块的指针WORD*
;
如果申请失败(如没有足够的空闲块),返回NULL
。
12. 释放内存时如何得知之前申请的空间大小
(1)在伙伴系统中,每个内存块都有一个 kval
字段,表示该内存块的大小为 (2^{kval}) 个 WORD_b
单元。
因此,在释放内存时,可以通过访问该内存块的 kval
字段来确定其大小。
void MyFree(FreeList* pf, WORD_b* p)
{// ...int size = 1 << p->kval; // 计算内存块的大小// ...
}
(2)在边界标识法中,每个内存块的头部都有一个size
字段,用于记录该内存块的大小。
因此,在释放内存时,可以直接访问该内存块头部的size
字段来确定其大小。
void MyFree(Space* pav, WORD* p)
{// ...int size = p->size; // 获取内存块的大小// ...
}
13. TCP请求相对于UDP有什么特点
- TCP比较可靠,是面向字节流的一对一传输协议。通过序列号、确认应答、流量控制和拥塞控制等手段保证可靠性。
14. TCP的滑动窗口机制用于什么场景,有什么作用
- 滑动窗口机制用于TCP发送端和接收端之间,根据网络带宽和接收方接收能力动态调整窗口大小,主要解决流量控制和拥塞控制问题。
15. 假设客户端一次性发10个序列包,在部分包未收到应答的情况下还能继续发送吗
- 不能,需要每个数据包都被接收方确认到达,发送窗口才会滑动,释放出空间才能发送新的数据包。
16. 在浏览器上输入域名到收到后台服务器返回的包,大概流程是怎样的
- 流程包括:浏览器解析网址;进行DNS解析,查询本地缓存,若没有则向DNS服务器请求,获取目标网址的IP地址;建立TCP连接;发送HTTP请求,请求包含请求方法、请求头;服务器处理请求,如访问数据库或读取文件;服务器发送HTTP响应,通常是HTML页面、CSS、图片等;浏览器解析HTML,构建文档对象模型树,进行CSS、JavaScript解析和页面渲染;加载页面资源,可能触发新的HTTP请求,并缓存已加载资源;关闭TCP连接,通过四次挥手完成。
17. 在局域网内部,服务器如何找到发送请求的设备
- 设备连接局域网会通过动态主机配置协议或静态IP配置获得唯一的局域网内IP地址。服务器通过ARP地址解析协议,发送ARP请求询问拥有该IP地址的设备,获取设备的Mac地址。若设备和服务器在同一子网,交换机根据目标IP地址或Mac地址将数据包发送到相应设备;若在不同子网,路由器通过IP地址转发数据包。
18. 找最长递增子序列(手撕+思路)
class Solution {
public:int lengthOfLIS(vector<int>& nums) {int n = (int)nums.size();if (n == 0) {return 0;}vector<int> dp(n, 0);for (int i = 0; i < n; ++i) {dp[i] = 1;for (int j = 0; j < i; ++j) {if (nums[j] < nums[i]) {dp[i] = max(dp[i], dp[j] + 1);}}}return *max_element(dp.begin(), dp.end());}
};
-加上输入输出后死活运行不出来,最后给面试官说了解题思路
- 采用动态规划方法,定义一个Vector类型的DP数组,DP数组的第i个元素表示数组中第i个元素的最长递增子序列的长度。对于原数组中的每个元素,从它前面找所有比它小的元素,若满足条件则在相应DP元素基础上延长长度,最终DP数组中的最大值就是最长递增子序列的长度。
- 时间复杂度是O(n^2),空间复杂度是O(n)。