一. 根据 int foo[8]的定义,int foo[8]={0,1,2,3,4,5,6,7};*((int*)((char*)&foo+sizeof(int)))的值是?
&foo:这是数组foo的地址,其类型是int(*)[8] (指向包含8个int的数组的指针)
[char*]&foo:里我们将&foo
的类型转换为char*.
这是因为char
类型通常被用作字节操作的基础类型,其大小为1字节(在大多数系统上)。
(char*)&foo + sizeof(int)
:这里我们将char*
指针向前移动了sizeof(int)
个字节。这相当于跳过了数组foo
的第一个元素(因为sizeof(int)
通常等于一个整数的大小)。
(int*)((char*)&foo + sizeof(int))
:现在我们将上述得到的char*
指针再次转换为int*
类型。
*((int*)((char*)&foo + sizeof(int)))
:最后,我们解引用这个int*
指针,即访问数组中第二个元素的值。
二. RT-Thread 支持邮箱和消息队列
在RT-Thread中,邮箱的长度为4字节。。而消息队列(Message Queue)则能够接收不固定长度的消息,消息的长度可以根据实际应用需求设定。
RT-Thread的邮箱和消息队列设计时就考虑到了线程安全和中断上下文的使用
RT-Thread的邮箱和消息队列都支持多种等待策略,包括按线程优先级等待和按先进先出(FIFO)方式获取消息。
三. bin文件或hex文件包含哪些部分
包含RO段和RW段,RO段中保存了Code和RO-data,RW段中保存了RW-data
四. 在RT-Thread中,主线程和空闲线程属于系统线程,用户编写的打印线程和处理中断服务的线程属于用户线程
五. 在Linux中,request请求和bio的关系?
通常一个 bio 对应一个 I/O 请求。I/O 调度算法可将连续的 bio 合并成一个请求,每个 request 里面会有多个 bio。所以,一个请求可以包含多个 bio。所以请求和bio的关系是一对多.
六. 在Linux中,块设备的结构?
包括三部分,段:由若干个块组成,是Linux内存管理机制中一个内存页或者内存页的一部分。
块:由Linux制定对内核或文件系统等数据处理的基本单位。通常由1个或多个扇区组成
扇区:块设备的基本单位,通常在512字节到32768字节之间,默认512字节
七. RISC和CISC的区别
RISC:精简指令集,执行的是等长精简指令集,可以同时执行多条指令。
CISC:复杂指令集,处理的是不等长指令集,执行单一指令集需要比较多的处理工作
八. 说说对MMU和TLB的理解
MMU是计算机系统的一种硬件设备,主要用于处理内存管理的任务,负责将程序中的虚拟地址映射到物理内存中的实际地址,以及管理内存访问权限。
TLB是MMU中的一种高速缓存,用于加速虚拟地址到物理地址的转换过程
九. volatile关键字作用?
1. 防止编译器过度优化
#include <stdio.h>int global_var = 0;void increment() {// 没有使用volatile,编译器可能优化掉这个操作global_var++;
}int main() {for (int i = 0; i < 1000000; i++) {increment();}printf("Final value of global_var: %d\n", global_var);return 0;
}
比如这一段代码,当没加volatile修饰变量的时候,编译器可能不会真正执行global_var++
的操作,因为从编译器的角度来看,global_var
的值在整个循环中都没有变化的必要,如果我们要运行验证的话,需要使用编译器的优化级别(如GCC的-O2
或-O3
)
十. 宏函数和内联函数的区别
宏函数由预处理器在编译时进行文本替换,而内联函数是由编译器在编译时将函数体代码插入到调用处。
内联函数提供类型检查,而宏函数不提供。
内联函数具有正常的作用域规则,而宏函数则没有作用域限制
十一. 虚拟地址怎么转换成物理地址
虚拟地址转换成线性地址,通过MMU的页表将线性地址转换为物理地址
十二. 简述TCP三次握手的过程
第一次握手:客户端创建传输控制块,然后向服务器发出连接请求报文(将标志位syn置1,随机产生一个序列号seq=x),客户端接着进入SYN_SENT状态
第二次握手:服务器收到请求报文,回复确认报文(SYN和ACK置1,ack=x+1,随机产生序列号seq=y)
第三次握手:检查ack是否等于x+1,ACK是否等于1,是则发送确认报文,将ACK置1,ack=y+1,序列号seq=x+1
十三. 简述TCP四次挥手的过程
第一次挥手:客户端发送FIN报文
第二次挥手:服务器确认FIN报文
第三次挥手:服务器发送FIN报文
第四次挥手:客户端确认FIN报文
十四. 为什么三次握手的时候ack=seq+1
告诉发送方收到了发出的同步信息
十五. 引用和指针区别
引用时变量的别名,指针是指向一段地址的变量
十六. 动态库和静态库的区别
1.扩展名不一样,静态库的扩展名一般为“.a”或“.lib”;动态库的扩展名一般为“.so”或“.dll”
2.链接时间不一样,静态库是在编译时链接,而动态库是在运行时链接
3.速度不一样,静态库的速度更快
十七. 异步IO和同步IO区别?
异步IO在调用一个功能时,得不到结果就去做下一件事,有结果后回调通知给调用者
同步IO在调用一个功能时,这个功能没有结束就一直等待它结束,必须做完一件事后再做下一件事,没有结果该调用就不会返回
十八. linux的进程状态?
七大详细状态
1. 运行态(正在运行或在运行队列中等待)
2. 就绪态
3. 中断睡眠状态(休眠中, 受阻, 在等待某个条件的形成或接受到信号)
4. 不可中断睡眠状态(收到信号不唤醒和不可运行, 进程必须等待直到有中断发生)
5. 僵尸态(进程已终止, 但进程描述符存在, 直到父进程调用wait4()系统调用后释放)
6. 暂停态
7. 终止态
五大最基本状态:创建、就绪、运行、阻塞、终止。
十九. 常见的操作系统进程调度策略有哪些?
时间片轮转,高优先级优先,先来先服务,短作业优先
二十. 逻辑地址、线性地址、物理地址、总线地址、虚拟地址的区别
逻辑地址:与内存段相关偏移的部分
线性地址=逻辑地址+基地址
物理地址=总线地址
虚拟地址=由内存管理单元(MMU)虚拟映射出来的地址
二十一. 死锁的必要条件是什么?
互斥、请求和保持条件、不可剥夺、环形链
二十二. 什么是优先级翻转,如何避免优先级翻转?
由于共享资源规则,导致高优先级线程被低优先级线程阻塞。解决办法:1、优先级天花板:将申请某资源的线程的优先级提升到最高;2、优先级继承:将占用资源的进程的优先级提升,与其他申请进程的优先级相同,等释放后再恢复。