嵌入式软件开发面试题(一)

目录

1.用预处理指令表示一年有多少秒

2.写出float x 与“零值”比较的if语句

3.为什么说if(0==x)比if(x==0)好?

4.将地0x8000中存放的整形变量,清除bit1。

5.linux下用shell命令在当前目录下创建myfolder目录,并将此目录的权限设为拥有者可读写群组和其他成员均可读不可写,且拥有者,群组和其他成员全都不可执行。

6.以下为32 位机器上的C 程序,请计算下列sizeof 的值.

7.简述代码编译后生成的map文件里面的内容?

8.在数据通信过程中,设置某普通串口的波特率为115200,则此串口每秒能传输多少KB数据。写出推导过程

9.如下代码的输出是什么?

10.如下ISR代码是否有问题? 如有问题指出问题点?

11.列举出10个Linux操作命令。

12.写出你熟悉的一个嵌入式芯片的型号、性能指标及资源分布情况

13.画出你最熟悉的一个实践项目的系统框图注:此题目,在纸上作答然后拍照上传

14.列举一个你在所做项目中遇到的技术问题,并描述分析问题的思路及最终解决问题的方法。

15.根据如下简易原理图,实现发光二极管的流水灯控制。要求控制方向依次从左到右从上到

16.进程和线程的区别??

17.静态局部变量和局部变量的区别


        总结一下最近看到的面试题吧!

        表达很重要,有时候不会表达你会这个别人也不知道,还有不要紧张不然会把会的的东西也说不出来。下面是我自己的理解不一定对哦,有不同的意见欢迎讨论。

1.用预处理指令表示一年有多少秒

        忽略了闰年。防止数据超过整型的限制,毕竟有些单片机的整型是16位的。或者8位的,单片机中整型的位数和CPU的位数是一致的。 当然如果整型是8位那长整型16也存不下哈哈,这题吧有些不太严谨。

#define UL unsigned long int
#define YEAR UL( 60 * 60 * 24 * 365)

2.写出float x 与“零值”比较的if语句

        之前看过B站李晓力嵌入式,正好看到这个了,说float和double是表示浮点型的,就是小数,小数不像整数,小数给个范围就有无数个。但是float是怎么表示一个小数的呢,他是由定点数乘以基数得到的,这个基数通常是2倍数

嵌入式软件开发面试题(一)_第1张图片

嵌入式软件开发面试题(一)_第2张图片 

 深入理解C语言浮点数类型 【C语言进阶必看】_哔哩哔哩_bilibili

所以比较浮点型要确定一个范围

float的精度只有7位1位整数6位小数

所以说只能是区域性的判断,我们在0.000001和-0.000001之间的数都被认为是0

if( (x > -0.000001) && (x < 0.000001)){}

3.为什么说if(0==x)比if(x==0)好?

        如果你少写了一个等号

        x = 0不会报错, 0 = x会报错,正确书写他俩的效果是一致的,就是在错误书写时可以让大家很好的判断出来。

4.将地0x8000中存放的整形变量,清除bit1。

        答案很多,直接操作地址用无符号整型就好,因为机器的位数永远和它的整型一致。

*( unsigned int *)0x8000 &= 0x1101;

*( unsigned int *)0x8000 &= ~(0x1 << 1);

        其实上面的第一种不好,但是当时我紧张就写了第一种这个形式,之前在ARM裸机开发的时候我们经常做寄存器的操作,开始都是这种取反左移在位运算的,后面知道了寄存器就是32位的才直接操作就写个32位的16进制数。不知道位数的时候最好用取反左移的形式,会自动变成对应位的16进制数,我第一种是默认他就0x8000这种16位的地址了。

5.linux下用shell命令在当前目录下创建myfolder目录,并将此目录的权限设为拥有者可读写群组和其他成员均可读不可写,且拥有者,群组和其他成员全都不可执行。

mkdir myfolder

sudo chmod 644 myfolder

因为不知道当前目录在用户目录下还是根目录下,加上sudo确保更改权限成功

三个数字分别是拥有者,组群和其它用户的权限每个用户用三位二进制表示分别是可读可写可执行

然后转化成对应10进制就行了。可读可写就是6可读不可写就是4.其实最前面还有一个d表示是文件还是目录

6.以下为32 位机器上的C 程序,请计算下列sizeof 的值.

char str[] = "hello world";
char *p1 = str;
int n = 100;
void *p2 = malloc(n);

第一个字符串算上结束标志大小是12

第二个一个指针32位机的话是4

第三个整型变量是4

第四个一个malloc申请空间后的指针还是一个指针所以还是4

7.简述代码编译后生成的map文件里面的内容?

        这题有点懵因为我用map文件只在编译内核依赖的时候用过,一个依赖于其它模块的模块在编译时要把对应模块的map拿过来。里面的内容分为五大块

Archive member included to satisfy reference by file (symbol)
调用的库函数信息:来自哪个.a中的哪个.o
Allocating common symbols
未初始化的全局变量:大小 变量出处
Discarded input sections
没有被调用的函数、变量
Memory Configuration
根据.ld文件中MEMORY来划分的内存区域:名称、起始地址、长度
Linker script and memory map
链接所需要的.o .a
根据.ld文件中SECTION来划分的区域:
.txt 代码段
.rodata 字符串和局部变量
.srodata 库中用到的rodata
.rela.dyn
.rela.text. 待重定位的函数信息
.data 数据段(大)
.sdata 数据段(小)
.bss 初始化为0的变量(大)
.sbss 初始化为0的变量(小)
COMMON 未初始化的变量
.attributes
.debug_info
.debug_abbrev
.debug_loc
.debug_aranges
.debug_line
.debug_str
.debug_frame
 

8.在数据通信过程中,设置某普通串口的波特率为115200,则此串口每秒能传输多少KB数据。写出推导过程

115200 / 10 = 11520 byte   //假设8N1的状态下

11520 / 1024 = 1.25 KB

 

9.如下代码的输出是什么?

int x, y, z;
x = y = 10;
z = ++x || ++y;
printf("x=%d, y=%d, z=%d", x, y, z);

逻辑或有一个不是0就结束了它的值也只是0或者1而位或才是每一位都或

当时草率了直接写的11 10 1

x=11,y=10,z=1

10.如下ISR代码是否有问题? 如有问题指出问题点?

#define PI 3.14
__interrupt double isr_function (double radius)
{
    double area = PI * radius * radius;
    printf("Area = %f", area);
    return area;
}

        ISR就是中断服务程序的英文缩写,中断服务程序不允许有参数传入也不能有返回值都要是void。

        printf是一个不可重入的函数,它的底层调用是全局的同一时间只能一个函数在用,可是写到中断中就未可知了,只能使用重定向到串口的printf或者自己封装的寄存器串口进行打印,其实直接用也不一定错误,就是很危险。通常在中断入口进行中断禁止结束在打开。

11.列举出10个Linux操作命令。

ls pwd touch vi(有可能不算,毕竟是程序的命令不确定算不算linux的,可是这个程序所有的linux都内置的,但是话又说回来所有的命令不都是封装好的程序么。)mkdir grep find chmod ping

tftp ifconfig fdisk echo cat nc nm 。。。。。

12.写出你熟悉的一个嵌入式芯片的型号、性能指标及资源分布情况

其实最熟悉的是32的c8t6哈哈,感觉太简单了,就写了一个比较熟悉的A核的exynos4412


exynos4412: 4核,1.5GHZ,4G内存,内核架构四颗CPU全是Ctrox-A9八级流水线,支持IC,uart,ADCHDMI,CAN,SPI,DMA等常见外设,使用精简指令集,采用32位架构

13.画出你最熟悉的一个实践项目的系统框图注:此题目,在纸上作答然后拍照上传

我把我的zigbee物联网仓储解决方案放上去了,B站有图,当时画了半小时呢,主要太大了,这次就简单画画

14.列举一个你在所做项目中遇到的技术问题,并描述分析问题的思路及最终解决问题的方法。

文件删了,懒着再写一次了,就把前几天移植FreeRTOs的那个问题写上去了。

15.根据如下简易原理图,实现发光二极管的流水灯控制。要求控制方向依次从左到右从上到

嵌入式软件开发面试题(一)_第3张图片

这题可挺经典,遇到好几次了,

也没说芯片型号只能写伪代码了,

//由于不知道芯片型号这里采取裸机伪代码的形式表述
//引用芯片的代码库
//由于矩阵LED的控制方式全是采取引脚控制基极,所以高电平导通 


int main()
{
	//初始化系统时钟及相关引脚时钟 
	//配置引脚寄存器 
	//通常使用一个寄存器管理一组引脚的输出情况,所以下面遍历可以采取位运算的形式
	//可以循环左移向高位遍历加if复位循环右移低位遍历if复位
	while(1){
		//也可以在这里恢复两个寄存器的初始状态,将出for循环的条件变成A7被置位和B8被置位。 
		for(;;){
			//由于顺序是左到右上到下外层遍历 V1-V4也就是PA8引脚到PA11引脚为高电平,在设置PA这组引脚某位
			//为高电平时其它引脚保证为低电平。 
			for(;;){
					//同理从左到右遍历 PB7到PB4. 
			}
		}
	}
} 

16.进程和线程的区别??

进程:进程是系统分配资源和调度的基本单位,也就是说进程可以单独运行一段程序。
线程:线程是cpu调度和分派的最小基本单位。

区别:
1.一个进程可以包含至少一个线程,一般来说也就是主线程,而一个线程只能属于一个进程;
2.进程拥有独立的内存,而线程没有独立的资源空间, 只是暂时存储在计数器,寄存器,栈中,同一个进程间的线程可以共享资源。
3.将代码放入到代码区之后,进程产生,但还没执行,我们所说的执行一般是是主线程main函数开始执行。
4.进程比线程更加消耗资源
5.进程对资源的保护要求高,而线程要求不高
6.进程是处理器这一层面的抽象,而线程是进程的基础上进一步并发的抽象
7.同一个进程下,一个线程的挂掉,会导致整个进程的挂掉,而进程之间不会相互影响
8.总的来说:我们都知道程序不能单独运行,只有将它放入内存中,分配资源才能运行,程序是指令的集合,而进程是程序的一次执行活动,属于动态概念
9.我们可以打个比方:进程相当于某一个大型项目,世界上可能有人同时在做这个项目,有其独特的方式;而线程就相当于这个项目下的一些程序员,多个程序员去完成这一个项目肯定要比一个人完成快的多,也就是能在同一时间操作。

决定同步:
1.互斥锁:同一个进程下,当某个线程使用进程的共享资源时,其他线程必须等待该线程结束
2.信号量:进程拥有同一时间最大访问数量


-----------------------------------
©著作权归作者所有:来自51CTO博客作者漫话人生的原创作品,请联系作者获取转载授权,否则将追究法律责任
进程和线程的定义和区别
https://blog.51cto.com/u_15711868/5455223

线程之间可以独立拥有的资源

线程独立的资源包括:
(1)线程ID:每个线程都有自己唯一的ID,用于区分不同的线程。

(2)寄存器组的值:当线程切换时,必须将原有的线程的寄存器集合的状态保存,以便重新切换时得以恢复。

(3)线程的堆栈:堆栈是保证线程独立运行所必须的。

(4)错误返回码:由于同一个进程中有很多个线程同时运行,可能某个线程进行系统调用后设置了error值,而在该线程还没有处理这个错误,另外一个线程就在此时被调度器投入运行,这样错误值就有可能被修改。所以,不同的线程应该拥有自己的错误返回码变量。

(5)线程优先级:线程调度的次序(并不是优先级大的一定会先执行,优先级大只是最先执行的机会大)。

17.静态局部变量和局部变量的区别

区别:

1、静态局部变量属于静态存储类别,在静态存储区内分配存储分配单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储区空间而不占静态存储空间,函数调用结束后立即释放。

2、对静态局部变量是在编译时赋初值的,即只赋值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。而对自动变量赋初值,不是在编译时进行的,而是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。

3、如在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0或空字符。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。这是由于每次函数调用结束后存储单元已释放,下次调用时又重新另分配存储单元,而所分配单元的值不确定。

4、虽然静态局部变量在函数调用结束后仍然存在,但其他函数不能引用它

你可能感兴趣的:(面试刷题,面试,嵌入式,C,线程,单片机)