【面试题】 gcc/g++编译器的使用
什么是gcc?
gcc命令使用GNU推出的基于C/C++编译器,可以用来编译C/C++、JAVA等语言的程序。
gcc和g++的区别是啥?
g++ 会把 .c /.cpp 文件当做是 C++ 语言,从而调用cc1plus进行编译,默认告诉链接器,让它链接上C++标准库
gcc 会把 .c 文件当做是 C 语言,从而调用cc1进行编译
gcc会把.cpp文件当成C++进行处理,从而调用cc1plus进行编译
gcc默认不会链接上C++标准库。
gcc的使用
语法:
gcc [选项] [参数]
选项
-o : 指定生成的输出文件名称
-E : 仅执行编译预处理
-S :将C语言源代码转换为汇编代码
-Wall: 显示警告信息
-c : 仅执行编译操作,不进行链接操作
参数
C语言源文件
实例
无选线编译链接:
gcc test.c //将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out。
选项 -o:
gcc test.c -o test //将test.c预处理、汇编、编译并链接形成可执行文件。这里未指定输出文件,默认输出为a.out。
选项 -E:
gcc -E test.c -o test.i // 将test.c预处理输出test.i文件。
选项 -S:
gcc -S test.i // 将预处理输出文件test.i汇编成test.s文件。
选项 -c:
gcc -c test.s // 将汇编输出文件test.s编译输出test.o文件。
无选项链接:
gcc test.o -o test // 将编译输出文件test.o链接成最终可执行文件test。
选项-O
gcc -O1 test.c -o test // 使用编译优化级别1编译程序。级别为1~3,级别越大优化效果越好,但编译时间越长。
多源文件的编译方法:
gcc testfun.c test.c -o test
分别编译各个源文件,之后对编译后输出的目标文件链接:
gcc -c testfun.c
gcc -c test.c
gcc -o testfun.o test.o -o test
//以上两种方法相比较,第一中方法编译时需要所有文件重新编译,而第二种方法可以只重新编译修改的文件,未修改的文件不用重新编译
【面试题】 TCP/IP网络协议的使用
TCP/IP(传输控制协议/互联网协议)是一组用于在互联网上进行通信的协议。下面是一个简单的TCP/IP示例,可以帮助你快速入门:
- 建立连接:
- 服务器端启动并等待客户端连接。
- 客户端发起连接请求到服务器的IP地址和端口号。
- 服务器接受连接请求,建立与客户端的连接。
- 数据传输:
- 客户端向服务器发送数据。
- 服务器接收到数据,并根据需要进行处理。
- 服务器向客户端发送响应数据。
- 客户端接收到响应数据,并根据需要进行处理。
- 连接关闭:
- 客户端或服务器端任意一方决定关闭连接。
- 发送一条关闭连接的消息给对方。
- 双方确认收到关闭消息后,关闭连接。
# 服务器端代码
import socket
# 创建套接字
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定IP地址和端口号
server_address = ('127.0.0.1', 8888)
server_socket.bind(server_address)
# 监听连接请求
server_socket.listen(1)
# 接受客户端连接
client_socket, client_address = server_socket.accept()
print('客户端已连接:', client_address)
# 接收数据
data = client_socket.recv(1024)
print('接收到的数据:', data.decode())
# 发送响应数据
response = 'Hello, Client!'
client_socket.send(response.encode())
# 关闭连接
client_socket.close()
server_socket.close()
# 客户端代码
import socket
# 创建套接字
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 服务器地址和端口号
server_address = ('127.0.0.1', 8888)
# 建立连接
client_socket.connect(server_address)
# 发送数据
message = 'Hello, Server!'
client_socket.send(message.encode())
# 接收响应数据
data = client_socket.recv(1024)
print('接收到的响应数据:', data.decode())
# 关闭连接
client_socket.close()
【面试题】通信协议
I2C
:
| start | 设备地址(7bit) | 方向(0写/1读) | 回应 | 数据 (8bit)| 回应 | 数据(8bit) | 回应 | P结束 |
回应1:用来确定这个设备是否存在;回应2:用来确定数据是否接收完成
采用主从结构,半双工传输方式(主设备负责发送读写命令,从设备响应,并返回相应的数据),使用2根信号线:SCL串行时钟线和SDA串行数据线,SCL提供时钟信号用于双向的数据传输,SDA用于双向传输数据。通信熟读相对较慢(百KHZ),具有很高的灵活性,支持多主设备、多从设备连接。有固定的传输协议,主设备通过地址来选择与之对应的通信从设备。
SPI
:
采用主从结构,全双工传输方式(主从设备可以同时发送和接收数据),使用4个信号线:片选信号线、时钟信号线、主入从出、主出从入。通信速度较快(百MHZ),没有固定的传输协议。
RS232
:
单端传输,点对点进行传输、使用两根信号线,信号电平正负3V到15V,传输距离为15米左右,抗干扰性能相对较弱。
RS485
:
半双工或全双工通信接口,可以实现多节点通信,信号电平正负2V到6V,传输距离最远可达1200米,采用差分信号线传输,具有较强的抗干扰能力。
UART
:
通信原理:CPU先把准备写入串行设备的数据放到UART的寄存器(临时内存块)中,再通过FIFO(First Input First Output,先入先出队列)传送到串行设备
UART作为异步串口通信协议的一种,工作原理是将传输数据的每个字符一位接一位地传输。
| 起始位 | 7bit数据位 | 校验位 | 停止位 | 空闲 | 下一个字符的起始位 |
起始位:先发出一个逻辑“0”的信号,表示传输字符的开始。
数据位:7位数据位构成一个字符,通常采用ASCII码。
空闲位:处于逻辑“1”状态,表示当前线路上没有资料传送。
波特率:每秒传输多少bit,衡量数据传输速率的指标。
CAN
:
USB
:
通用串行总线是连接计算机系统与外部设备的一种串口总线标准 。
【面试题】常用ARM指令集
MOV R0, R1 @ 将R1里面的数据复制到R0中
MRS R0, CPSR @ 将特殊寄存器中的数据赋值到R0中
MSR CPSR, R1 @ 将R1里面的数据复制到特殊寄存器CPSR里。
@ 0x12 立即数
push {LR} @ 将LR进行压栈
pop {LR} @ 恢复LR
B <label> @ 跳转到label
BL <label> @ 跳转到label标号地址,并将返回地址保存在LR中
ADD Rd, Rn, Rm @ 加法运算:Rd = Rn + Rm
ADC Rd, Rn, Rm @ 带进位的加法运算, Rd = Rn + Rm + 进位
SUB Rd, Rn, Rm @ 减法运算:Rd = Rn + Rm
SBC Rd, Rn, Rm @ 带进位的减法运算:Rd = Rn - Rm - 借位
MUL Rd, Rn, Rm @ 乘法运算:Rd = Rn * Rm
UDIV Rd, Rn, Rm @ 无符号除法运算:Rd = Rn / Rm
SDIIV Rd, Rn, Rm @ 有符号除法运算:Rd = Rn / Rm
【面试题】 shell
写1到10数字相加程序
# !/bin/bash
sum = 0
for i in {1 .. 10}
do
sum = $((sum + i))
done
echo "1到10的数字相加结果为: $sum"
【面试题】 Makefile
Makefile文件是一个文本文件,其中包含了项目中的构建规则和指令,可以告诉计算机如何自动化地构建软件项目,从而提高开发效率。
Makefile文件的基本结构由以下几个组成部分组成:
- 目标:描述需要生成或更新的文件、程序或其他任务。
- 依赖关系:指定目标所依赖的其他文件或任务。
- 命令:定义生成目标所需执行的操作指令。
main: main.o input.o calcu.o
gcc -o main main.o input.o calcu.o
main.o: main.c
gcc -c main.c
input.o: input.c
gcc -c input.c
calcu.o: calcu.c
gcc -c calcu.c
clean:
rm *.o
rm main
【面试题】RTOS
Linux的任务调度?
时间片的最小单位是什么?用什么方式计算出来?
在RTOS中,时间片的最小单位是以时钟节拍 (Tick) 表示的。时间片的最小单位就是根据时钟节拍速率来计算的,即时间片长度 = 1 / 时钟节拍速率。
怎么获取每个线程的执行时间?
在RT-Thread中,可以使用相应的API获取当前线程的指针,并通过访问线程控制块中的成员来获得线程的执行时间。
RTOS任务的优先级?
任务的优先级是通过设置任务的优先级属性来实现的。任务的优先级值范围为0到最高优先级值(默认为32)。数字越小,优先级越高。
要设置任务的优先级,可以使用rt_thread_create()函数创建任务时传递一个优先级参数。
在RT-Thread中,线程的优先级通过就绪列表实现,就绪列表由线程就绪优先级组和线程优先级表组成。线程启动的时候将根据优先级插入到线程就绪优先级组的位置,线程就绪优先级组的每一位对应一个优先级,每个优先级对应一个优先级表。
然后时间片轮转算法会按照优先级顺序从高到低依次执行每个线程的运行。如果两个线程的优先级相同,则采用时间片轮转算法来切换这两个线程。这样可以保证高优先级线程得到更多的CPU时间,同时避免低优先级线程饥饿的情况。
如何保证任务在规定时间内执行完?
使用定时器:通过设定合适的定时周期,确保任务在规定的时间内被触发执行。
使用软件定时器:RT-Thread还提供了软件定时器的功能,即通过轮询方式执行任务。
RTOS任务抢占机制
RT-Thread采用基于优先级的抢占式调度算法,即当一个高优先级任务就绪时,就会抢占正在运行的低优先级任务的CPU资源,以确保高优先级任务及时地执行。
RTOS内存管理,内存分配?
在RT-Thread中,内存管理和内存分配是通过内存堆实现的。RT-Thread提供了几种内存管理方案,包括静态内存池和动态内存堆。
动态内存堆:在动态内存池中分配用户指定大小的内存块。优点:按需分配,在设备中灵活使用。缺点:内存池中可能出现碎片。
静态内存池:在静态内存池中分配用户初始化的时候预先设置固定大小的内存块。优点:分配和释放效率高,静态内存池中没有碎片。缺点:只能申请到初始化预设大小的内存块,不能按需申请。
动态分配内存与静态分配内存的区别:静态内存一旦创建就指定了内存块的大小,分配只能以内存块大小粒度进 行分配;动态内存分配则根据运行时环境确定需要的内存块大小,按照需要分配内存。