与驱动有关的面试问题

以下内容源于网络资料的整理学习。

参考博客

嵌入式驱动那年的笔试面试-有干货_BeyondTheBoundary的博客-CSDN博客_芯动科技嵌入式笔试

嵌入式驱动工程师面试题集锦_shx516857593的博客-CSDN博客

嵌入式面试中可能问到的题目和答案整理(内核驱动篇)_kuensan的博客-CSDN博客_嵌入式驱动面试题

驱动软件工程师笔试题_Cawen_Cao的博客-CSDN博客

一、技术面试题

1、linux中内核空间、用户空间的区别?

Linux系统采取两级保护机制,对应两种不同的操作权限,内核空间权限高于用户空间权限。

内核空间和用户空间都有属于自己的虚拟空间。在32位系统中,cpu最高有32位寻址范围,即对应4G空间,内核空间被划分在高1G虚拟空间,用户空间在低3G。

普通应用程序运行在用户空间,执行一些贴近用户的低权限操作;系统内核程序、操作硬件的驱动程序等一些要求高级权限的程序运行在内核空间。

用户空间程序不能直接访问内核空间的数据,内核空间程序也一样不能直接访问属于用户进程空间的数据,用户空间和内核空间之间的通信必须通过一些特定的方法。

2、用户空间与内核通信方式

常用的也就这几种:

(1)系统调用。用户空间进程通过系统调用进入内核空间,访问指定的内核空间数据。

(2)驱动程序。用户空间进程可以使用封装后的系统调用接口访问驱动设备节点,以和运行在内核空间的驱动程序通信。

(3)proc文件系统。proc文件系统的主要功能是在内核空间提供一套机制为用户空间方便的查询,查看,设置内核信息,多用于查询类操作。

(4)共享内存mmap。在代码中调用接口,实现内核空间与用户空间的地址映射,在实时性要求很高的项目中为首选,省去拷贝数据的时间等资源,但缺点是不好控制。

(5)copy_to_user()、copy_from_user(),是在驱动程序中调用接口,实现用户空间与内核空间的数据拷贝操作,应用于实时性要求不高的项目中。

3、linux中内存划分及如何使用?虚拟地址及物理地址的概念及彼此之间的转化?高端内存概念?

(1)内存划分

以32位机器为例,cpu最大寻址范围为4G,Linux系统将4G虚拟地址空间划分为高1G,低3G。

低3G虚拟空间属于用户空间,都是经过映射的线性地址,供用户进程空间使用。

高1G并非都是像用户空间一样都是映射过的线性空间,Linux系统将高1G划分为三部分:DMA区,常规区,高端内存,其中0-896都是映射过的线性空间,剩下的896-1024即高端内存,这段高端内存都是未经过映射的虚拟地址,Linux系统利用这些有限的虚拟地址,临时动态的映射到大于896M的物理空间地址,实现了利用有限的虚拟地址访问到物理内存的所有地址。

(2)内存申请函数的对比

malloc用于用户空间进程申请内存空间,kmallc和vmalloc在内核空间使用。

kmalloc申请到的内存空间,是线性连续的,可以用于dma。

vmalloc申请的内存是逻辑连续的,但是物理地址不连续,常用与申请大的内存,请注意vmalloc可能会睡眠,在中断、阻塞的环境下不能使用。

(3)内存映射方式

虚拟地址到物理地址的转化,用户空间和内和空间采用不同的映射机制。用户空间的地址映射经过mmu(内存管理单元)管理。而内核空间的虚拟地址到物理地址的映射是一一对应的,例如虚拟空间地址0xc0000004,对应的物理地址空间地址为:0xc0000004 - 0xc0000000 = 0x04,以此类推。(待求证)。

4、inux中中断的实现机制,tasklet与workqueue的区别及底层实现区别?为什么要区分上半部和下半部?

中断的上下半部_天糊土的博客-CSDN博客_中断下半部

(1)Linux中断分为硬件中断和内部中断(异常),调用过程:外部中断产生->发送中断信号到中断控制器->通知处理器产生中断的中断号,让其进一步处理。即处理器收到来自中断控制器的中断处理请求,保存中断上下文,跳转到中断对应的处理处,(快速完成中断中断上半部,中断上半部返回后执行中断下半部),中断处理函数返回时恢复现场。

(2)tasklet和workqueue,两者都是中断下半部的一种实现方法。区别在于tasklet属于中断上下文,支持smp、不可睡眠和阻塞;workqueue基于线程的封装,属于进程上下文,因此支持睡眠、阻塞。

(3)为了能够在中断处理过程中被新的中断打断,将中断处理程序一分为二,上半部登记新的中断,快速处理简单的任务,剩余复杂耗时的处理留给下半部处理。下半部处理过程中可以被中断,上半部处理时不可被中断。

5、Linux的同步机制

常见的同步接口,包括进程同步,信号量,自旋锁,互斥锁,条件变量,读写锁。

多进程并发一般考虑使用信号量机制,在线程并发时多采用互斥锁,条件变量。

(1)条件变量在某些角度就是线程版的信号量实现,因为两者都是在考虑持有锁时间较长情况下使用。

(2)互斥锁,自旋锁一般都是用在持有锁时间不会很长的情况下,在自旋锁有使用意义的前提下,如果持锁时间会非常短则自旋锁效率高于互斥锁(否则应该使用互斥锁,因为互斥锁会持续占有cpu资源,不宜过长,而互斥锁会导致抢不到锁的线程睡眠,进入等待队列)。

(3)互斥锁和自旋锁都可以用在进程上下文,而在中断上下文只能使用自旋锁,因为互斥锁会睡眠。

(4)使用自旋锁的进程不能睡眠,使用信号量的进程可以睡眠。

7、/dev/下面的设备文件是怎么创建出来的?

有三种方式:devfs机制、udev机制、手动创建设备节点。

谈谈个人见解:

devfs机制,从来没用过,应该是2.6以前的内核使用的;

udev机制,其实就是现在常用的device_create()、class_create()这一套接口,所谓udev是上层用户空间程序,是基于驱动中创建使用了这两个接口而起作用的,但是udev在日常开发中几乎接触不到,我们只需在驱动中调用创建节点的这两个API就ok了,剩下的工作就交给udev去做。

mknod ,新手最常用的一种创建设备节点方法,但并非入门后就再没有用途。在某些情境下,或许有人不想使用udev机制,于是把节点创建工作写在脚本里,这样也是无可厚非的。

8、原子操作该怎么理解?

原子操作,就是开始执行到执行结束期间不会被打断的操作单元。

9、insmod一个驱动模块,会执行模块中的哪个函数?rmmod呢?这两个函数在设计上要注意哪些?遇到过卸载驱动出现异常没?是什么问题引起的?

分别会执行module_init()、module_exit()指定的init函数和exit函数。

要注意的就是尽量使在init函数中出现的资源申请及使用有对应的释放操作在exit中,init申请,eixt释放。

卸载出现的异常?那很稀松平常了,大多数都是资源使用完没释放,但是模块却卸载了。

10、在驱动调试过程中遇到过oops没?你是怎么处理的?

遇到过,这种类似的段错误其实最好处理,因为它有call trace,根据堆栈信息去代码里面查看就行了。

如果代码中看不到明显低级错误,就需要printk联机调试,然而这种很少。

11、ioctlunlock_ioctl有什么区别?

ioctl是老的内核版本中的驱动API,unlock_ioctl是当下常用的驱动API。

区别在于ioctl调用前后,使用了大内核锁,而unlock_ioctl顾名思义就是没加大内核锁的新接口,改变的只是驱动调的方法,用户应用程序调用的接口不变。

大内核锁是Linux hacker在应付多处理器初期提出的一种锁,目的在于当一个处理核心在运行内核时,加上大内核锁,不让其他cpu核心同时运行内核程序,显然这样是有用的,然而这样大大降低了多处理器的存在意义,于是跟随时代更迭,大内核锁被一步一步的剔除,ioctl接口的升级就是典范!我觉得这样的问题太没有意义了,对开发有多大用处?

12、驱动中操作物理绝对地址为什么要先ioremap?

ioremp是内核中用来将外设寄存器物理地址映射到主存上去的接口,即将io地址空间映射到虚拟地址空间上去,便于操作。为什么非要映射呢,因为保护模式下的cpu只认虚拟地址,不认物理地址,给它物理地址它并不帮你做事,所以你要操作外设上的寄存器必须先映射到虚拟内存空间,拿着虚拟地址去跟cpu对接,从而操作寄存器。

11、设备驱动模型三个重要成员是?platform总线的匹配规则是?在具体应用上要不要先注册驱动再注册设备?有先后顺序没?

(1)总线,设备,驱动。

(2)匹配规则:当有一个新的设备挂起时,总线被唤醒,match函数被调用,用device名字去跟本总线下的所有驱动名字去比较,相反就是用驱动的名字去device链表中和所有device的名字比较。如果匹配上,才会调用驱动中的probe函数,否则不调用。

(3)至于先后顺序,鉴于个人理解,不会有影响,不管谁先谁后,bus都会完成匹配工作。

(4)谈谈对Linux设备驱动模型的认识:设备驱动模型的出现主要有三个好处

设备与驱动分离,驱动可移植性增强;

设备驱动抽象结构以总线结构表示,看起来更加清晰明,谁是属于哪一条bus的;

最后,设备与驱动分离,很好的奠定了热插拔机制。

12、linux中RCU原理?

rcu是2.6出现的一种读写锁,可以说是老的读写锁的升级版,主要用在链表这种数据结构上,经典使用场景是多读者少写者的情况,rcu允许多个读者一个写者共同操作数据而不必加锁,这是经典用法,若出现多个写者时,写者与写者之间就得自己手动同步。当要删除一个节点时,删除后并不会马上释放节点,而是会等待在删除动作之前已经开始读该节点的读者都完成读操作之后才会释放此节点,这段时间被称为宽限期。

13、谈谈Linux软中断?

Linux系统中的软中断,是专为一些不是特别要紧的耗时任务而产生的一种机制,多数用在中断处理过程中,典型应用就是用于中断下半部,tasklet机制就是基于软中断的典型下半部应用。

软中断就是结合任务调度、延迟处理等让守护进程去处理一些不是特别紧急又耗时的任务

14、linux系统实现原子操作有哪些方法?

答:提到原子操作,我首先想到的是针对整型的原子操作,atomic_t类型,这里面有一整套针对整型的原子操作API可以调用。既然整型能原子操作,那其他也应该可以吧,结合原子操作的定义,要想对其他类型结构实现原子操作,那就加锁咯,将需要原子操作的部分放在临界区。

15、linux中系统调用过程?

系统调用,比如open()函数,它并不是真正的系统调用实现函数,其实它只是一个c库函数。

内部实现做了两件事,先把系统调用号传递给内核,最后拉起一次软中断,自此cpu进入内核态运行。

内核在软中断向量表中找出对应的中断类型,根据中断类型找到对应的软中断执行函数,然后执行函数根据系统调用号,在系统调用号表里面找到对应的系统调用函数。

16、谈谈linux内核的启动过程(源代码级)?

首先,内核镜像自解压,解压完之后从head.s开始运行,即引导内核,在内核引导期间将会设置内核参数。

随后,跳转到第一个c函数start_kernel(),进入内核启动阶段,在内核启动过程中进行一些必要的硬件初始化工作。

在内核启动最后,挂载文件系统,然后创建第一个用户空间进程,init进程,进一步完成驱动挂载,用户服务初始化工作。

17、谈谈Linux调度原理?

Linux将进程按权限分为两大类,常规进程和实时进程

常规进程对应一种调度算法,实时进程有两种对应着两种不同的调度算法。

进程按照状态又可以分为几种,常见的状态有:运行态、可中断睡眠态、不可中断睡眠态、停止态。处于运行态的进程根据调度算法接受调度在cpu上运行。

18、谈谈对Linux网络子系统的认识?

网络子系统可以概括描述为

应用程序—》系统调用接口(主要是指socket接口)—》协议无关接口(由socket实现,提供一套通用接口支持不同的协议)—》网络协议(包括tcp、udp在内的网络协议)—》设备无关接口(由net_device接口组织的一组通用接口,将网络协议与各种网络设备联系起来)—》设备驱动(即各种网络设备的驱动程序,负责管理具体的网络设备)—》网络设备(具体的网络硬件设备)。

19、内核中申请内存有哪几个函数?有什么区别?

常见的三个接口,kmalloc(),vmalloc(),__get_free_pages()。

kmalloc()操作的空间位于直接映射区(即4G空间中的896M区域),申请到空间物理地址多为连续地址,常用于操作频繁的数据结构,连续地址利于提高访问效率。

对于一些操作不频繁的数据结构可以用vmalloc()申请内存,vmalloc()操作的空间优先选择高端内存,这里申请出的内存物理地址往往不是连续的,所以访问效率不会很高。

__get_free_pages()操作的区域跟kmalloc()相同,位于直接映射区,不同的是它申请的是物理页的整倍数大小的内存。

20、谈谈内核函数mmap的实现机制?

(1)mmap函数,把一个文件映射到一个内存区域,从而我们可以像读写内存一样读写文件,其比单纯调用read/write要快上许多。在某些时候我们可以把内存的内容拷贝到一个文件中实现内存备份,当然也可以把文件的内容映射到内存来恢复某些服务。

(2)mmap实现共享内存也是其主要应用之一,mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。

21、中断上半部、下半部的实现理解

(1)当中断到来时,要完成的工作往往并不会是短小的,它可能要进行较大量的耗时处理。因此中断处理程序中,不要求立即完成的,可以交由中断下半部完成。

中断上半部主要完成尽可能少的、比较紧急的功能,例如简单地读取寄存器中的中断状态并清除中断标志后就进行“登记中断”的工作。顶半部执行的速度就会很快,可以服务更多的中断请求。

复杂的内容则交由中断下半部来执行,而且中断下半部可以被新的中断打断,这也是下半部和上半部的最大不同。

当然, 如果中断比较简单,就不用区分上下半部。

(2)Linux 系统实现下半部的机制主要有三种:tasklet,workqueue,软中断。  

22、tasklet与workqueue的区别及底层实现区别

(1)softirq和tasklet都属于软中断,tasklet是softirq的特殊实现;workqueue是普通的工作队列。  

(2)tasklet和workqueue,两者都是中断下半部的一种实现方法。区别在于tasklet属于中断上下文,支持smp、不可睡眠和阻塞;workqueue基于线程的封装,属于进程上下文,因此支持睡眠、阻塞。

23、软中断的理解(与硬件中断的对比)

软中断过程:

(1)当某一软中断时间发生后,首先需要设置对应的中断标记位,触发中断事务(raise_softirq()设置软中断状态bitmap,触发软中断事务)。

(2)然后唤醒守护线程去检测中断状态寄存器(在Linux中 软中断daemon线程函数为do_softirq())。

(3)如果通过查询发现某一软中断事务发生之后,那么通过软中断向量表调用软中断服务程序action()。

和硬件中断的对比:

(1)一个软中断不会去抢占另一个软中断,只有硬件中断才可以抢占软中断,所以软中断能够保证对时间的严格要求。

(2)软中断与硬件中断不同在于,从中断标记到中断服务程序的映射过程。

硬件中断发生之后,CPU需要将硬件中断请求通过向量表映射成具体的服务程序,这个过程是硬件自 动完成的。

但是软中断不是,其需要守护线程去实现这一过程,这也就是软件模拟的中断,故称之为软中断。

24、请简述自旋锁、信号量两个概念,及它们的区别。

(1)自旋锁

自旋锁是专门为防止多处理器并发而引入的一种锁,在内核中大量应用于中断处理等部分。(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,不需要自旋锁)。

自旋锁最多只能被一个内核任务持有,如果一个内核任务试图请求一个已被争用(已经被持有)的自旋锁,那么这个任务就会一直进行忙循环——旋转——等待锁重新可用。要是锁未被争用,请求它的内核任务便能立刻得到它并且继续进行。

自旋锁可以在任何时刻防止多于一个的内核任务同时进入临界区,因此这种锁可有效地避免多处理器上并发运行的内核任务竞争共享资源。

自旋锁的初衷,是在短期间内进行轻量级的锁定。一个被争用的自旋锁使得请求它的线程在等待锁重新可用的期间进行自旋(特别浪费处理器时间),所以自旋锁不应该被持有时间过长。如果需要长时间锁定的话, 最好使用信号量。

因为自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。这点很好地满足了对称多处理机器需要的锁定服务。在单处理器上,自旋锁仅仅当作一个设置内核抢占的开关。如果内核抢占也不存在,那么自旋锁会在编译时被完全剔除出内核。

简单的说,自旋锁在内核中主要用来防止多处理器中并发访问临界区,防止内核抢占造成的竞争。另外自旋锁不允许任务睡眠(持有自旋锁的任务睡眠会造成自死锁——因为睡眠有可能造成持有锁的内核任务被重新调度,而再次申请自己已持有的锁),它能够在中断上下文中使用。

死锁:假设有一个或多个内核任务和一个或多个资源,每个内核都在等待其中的一个资源,但所有的资源都已经被占用了。这便会发生所有内核任务都在相互等待,但它们永远不会释放已经占有的资源,于是任何内核任务都无法获得所需要的资源,无法继续运行,这便意味着死锁发生了。自死琐是说自己占有了某个资源,然后自己又申请自己已占有的资源,显然不可能再获得该资源,因此就自缚手脚了。

自旋锁的基本形式如下:
spin_lock(&mr_lock);
//临界区
spin_unlock(&mr_lock);

(2)信号量

Linux中的信号量是一种睡眠锁。如果有一个任务试图获得一个已被持有的信号量时,信号量会将其推入等待队列,然后让其睡眠。这时处理器获得自由去执行其它代码。当持有信号量的进程将信号量释放后,在等待队列中的一个任务将被唤醒,从而便可以获得这个信号量。

信号量的睡眠特性,使得信号量适用于锁会被长时间持有的情况;只能在进程上下文中使用,因为中断上下文中是不能被调度的;另外当代码持有信号量时,不可以再持有自旋锁。

信号量基本使用形式为:
static DECLARE_MUTEX(mr_sem);//声明互斥信号量
if(down_interruptible(&mr_sem))
//可被中断的睡眠,当信号来到,睡眠的任务被唤醒
//临界区
up(&mr_sem);

(3)信号量和自旋锁区别

1、如果代码需要睡眠(往往发生在和用户空间同步时),使用信号量是唯一的选择。由于不受睡眠的限制,使用信号量通常来说更加简单一些。

2、如果需要在自旋锁和信号量中作选择,应该取决于锁被持有的时间长短。理想情况是所有的锁都应该尽可能短的被持有,但是如果锁的持有时间较长的话,使用信号量是更好的选择。

3、信号量不同于自旋锁,它不会关闭内核抢占,所以持有信号量的代码可以被抢占。这意味者信号量不会对影响调度反应时间带来负面影响。

26、什么是GPIO?

general purpose input/output ,即可以把这些引脚拿来用作任何一般用途的输入输出,例如用一根引脚连到led的一极来控制它的亮灭,也可以用一根(一些)引脚连到一个传感器上以获得该传感器的状态,这给cpu提供了一个方便的控制周边设备的途经。

27、在Linux C中,ls这个命令是怎么被执行的?

使用fork创建一个进程或exec函数族覆盖原进程。

28、写一段 C 代码让程序跳转到地址是 0x8000 0000 的位置执行

(*(void(*)(void))0x100000)();或者((void(*)(void))0x100000)();

29、简要叙述进程和线程这两个概念。

进程是指一个程序在一个数据集合上的一次运行过程。

线程是进程中的一个实体,是被系统独立调度和执行的基本单位。

进程是程序的一次执行。线程可以理解为进程中执行的一段程序片段。

30、在一个只有128M内存并且没有交换分区的机器上,说说下面两个程序的运行结果

1、
#define MEMSIZE 1024*1024
int count = 0;
void *p = NULL;
while(1) {
  p = (void *)malloc(MEMSIZE);
  if (!p) break;
  printf("Current allocation %d MB\n", ++count);
}
2、
while(1) {
  p = (void *)malloc(MEMSIZE);
  if (!p) break;
  memset(p, 1, MEMSIZE);
  printf("Current allocation %d MB\n", ++count);
}

第一道程序分配内存但没有填充,编译器可能会把内存分配优化掉,程序死循环。

第二道,程序分配内存并进行填充,系统会一直分配内存,直到内存不足,退出循环。

31、请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句

如果可以用小于号的话,可以这么写:#define compare(a,b) ((a-b)<0 ? -1 : ((a-b) == 0 ? 0 : 1))
这样一来的话:
compare(a,b) == -1表示a<b
compare(a,b) == 0表示a==b
compare(a,b) == 1表示a>b

但是如今不能用小于号,那么我们怎样不用小于号来判断一个数字是否小于0呢?我们可以用:abs(t) != t ? 1 : -1来表示。
也即如果abs(t) != t那么t<0,否则t>=0。也即t<0等价于(abs(t) != t ? 1 : -1) == 1那么前面的宏写成如下:
#define compare(a,b) ((abs(a-b) != (a-b) ? 1 : -1) == 1 ? -1 : ((a-b) == 0 ? 0 : 1))
代码:

//利用宏比较大小
#include <iostream>
#include <cmath>

#define compare(a,b) ((abs(a-b) != (a-b) ? 1 : -1) == 1 ? -1 : ((a-b) == 0 ? 0 : 1))

int main()
{
    int a1 = -1, b1 = 2, a2 = 3, b2 = 3, a3 = 4, b3= 2;

    cout << compare(a1, b1) << endl << compare(a2, b2) << endl << compare(a3, b3) << endl;
    
    return 0;
}

32、触摸屏的硬件原理

触摸屏技术原理介绍 |中国触摸屏网

http://www.cublog.cn/u2/78837/showart_1186312.html

触摸屏的主要三大种类是:电阻技术触摸屏、 表面声波技术触摸屏、 电容技术触摸屏。

电阻触摸屏的主要部分是一块与显示器表面非常配合的电阻薄膜屏, 这是一种多层的复合薄膜,它以一层玻璃或硬塑料平板作为基层,表面图有一层透明氧化金属 (ITO氧化铟,透明的导电电阻) 导电层,上面在盖有一层外表面硬化处理、光滑防擦的塑料层 、它的内表面也涂有一层ITO涂层 、在他们之间有许多细小的(小于1/1000英寸)的透明隔离点把两层导电层隔开绝缘 。当手指触摸屏幕时,两层导电层在触摸点位置就有了接触,控制器侦测到这一接触并计算出(X,Y )的位置,再根据模拟鼠标的方式运作。这就是电阻技术触摸屏的最基本的原理。

表面声波技术是利用声波在物体的表面进行传输,当有物体触摸到表面时,阻碍声波的传输,换能器侦测到这个变化,反映给计算机,进而进行鼠标的模拟。

电容技术触摸屏利用人体的电流感应进行工作 。用户触摸屏幕时 ,由于人体电场,用户和触摸屏表面形成以一个耦合电容, 对于高频电流来说,电容是直接导体,于是手指从接触点吸走一个很小的电流。

33、其他问题

  1. 二分查找
  2. 校验
  3. 关于字符串:
  4. 关于数据结构
  5. 关于其他简答题:
  6. 关于编程
    (一) 1.5n次比较,求出数组的最大值和最小值(数组乱序)
    (二) 环形缓冲区,用数据结构实现?
    (三) 链表的删除,头部插入,尾部插入实现?
    (四) 求出一个字符串的最长重复串,如“ababc”,返回“ab”
    (五) 求出一个周期字符串的最长周期,如“abcabc”,返回3
    (六) 使用C/C++实现一个单向链表,链表需要支持如下接口:
    (七) 网络字节序转换,大端小端。
    (八) 打开一个设备,读取文件,打印输出。
    (九) 给一个整数,转换为十六进制字符输出
    (十) 给在 32 位处理器上,将任一整数转换为二进制形式。
  7. C语言宏中”#”和”##”的用法
  8. 关于IPv6:
  9. Arm有多少32位寄存器?
  10. HAL层:硬件抽象层
  11. Arm2440和6410有什么区别?
  12. 开发板时钟(2410和6410对比)什么是PLL(锁相环):
  13. Arm开发板的资源,主频多大?内存多大?
  14. CPU,MPU,MCU,SOC,SOPC联系与差别
  15. 线程池怎么设计
    (一) 什么是线程池?
    (二) 为什么要用线程池?
    (三) 线程的工作流程
    (四) 线程池设计
  16. free函数怎么知道释放内存大小
  17. 构造函数和析构函数抛出异常
  18. tcp/udp上层网络协议举例并说明原理
    (一) HTTP:
    (二) TFTP:
  19. 关于内存泄漏
  20. 一个服务器对10000客户端,服务器上的线程模型
  21. 代码效率优化怎么搞
  22. GPIO三种状态:输入输出和高阻态
  23. 上拉和下拉:
  24. GPIO外部有三种情况:1)直接接地2)直接接电源3)悬挂。请问在GPIO内部可以实现上拉和下拉的情况下如何判断这三种情况?
  25. 串口协议讲一讲?
  26. RS232和RS485通讯接口有什么区别?
  27. IIC时序图画一下,IIC有哪些状态,给一个字节,将它发送出去。IIC有什么注意事项?有没有用I/O模拟IIC,如果有需要注意什么?
  28. 讲解一下IIC总线
  29. Bootloader的流程
  30. 为什么2440的内存起始地址是3后面7个0呢?
  31. 为什么6410的内存起始地址是5后面7个0呢?
  32. 三个字节char型,上电为随机数,求三者之和为零的概率
  33. VS中Debug和Release的区别
  34. Zigbee的传输速率多大?(智能家居)为什么用它,和其他传输有什么区别?WIFI安全吗,为什么?
  35. 用户和内核如何通讯?(追问:驱动程序中如何从用户到内核)
  36. 计算机访问哪个最快?
  37. 线程和进程的区别?
  38. 设计模式有哪些?
  39. 软件的设计流程?
  40. 指针和引用的区别?
  41. 内存管理有什么看法?(MMU)
  42. 锁有哪些?有什么注意事项
  43. 信号量和自旋锁区别
  44. 中断能不能睡眠,为什么?下半部能不能睡眠?
  45. 上下文有哪些?怎么理解?
  46. 死锁产生的原因及四个必要条件
  47. 驱动中首先执行什么?
  48. 触摸屏和lCD驱动中做了什么,流程是什么?
  49. 输入子系统上报系统有什么函数?怎么知道有没有上报成功?
  50. 总线设备驱动模型之间是什么关系?设备和驱动之间的如何匹配,匹配规则是否可变?
  51. 什么是交叉编译?为什么需要交叉编译?为什么还要主机编译
  52. 简述linux系统启动过程
  53. Linux设备中字符设备和块设备有什么主要区别?分别举例。
  54. 主设备号和次设备号的用途
  55. Linux下rs232和rs485编程有什么区别?
  56. Uart和IIC和SPI的区别(提示:关于异步和同步,电子器件上的)?
  57. 用串口发送十个字节就丢失一个两个你会怎样检查;发送的时候对方设备不响应你该怎么办
  58. IIC,scl频率多大
  59. 触摸屏中断做了什么,LCD中断做了什么?
  60. zigbee用的哪家方案?zigbee端点类型有哪些,这些概念的区别?端点能够中转吗?一个端点上有哪些设备?你做的项目或者实践有多少节点?zigbee上有操作系统吗?
  61. 客户端是否单独连接服务器(客户端和客户端直接是否点对点连接)?客户端之间有没有交互?有没有考虑服务器进程如果崩溃了,客户端资源没有得到释放怎么做?那么如果服务器正常,客户端中途断开连接怎么办?如果发送文件,是直接点对点吗,也就是客户端之间直接通讯?线程池中线程之间是分离的吗?
  62. 没有使用MySQL之类的吗?sqlite是线程安全的吗
  63. 视频监控系统这个项目能不能做图像的简单处理,比如截取?网页中如果要打印换行符,怎么打印?这个项目中做的驱动中,你这个视频子系统用的是不是内核的?
  64. QT,用的熟吗?做的驱动有没有编入内核?既然没有编入内核,那是需要手动去启动和装载吗?需不需要创建设备节点?用户是如何访问这些驱动的?做的驱动都是字符设备吗?
  65. 你这个项目中zigbee用的是哪家的方案?控制设备有哪些?有多少节点?也就是说只是一对用于通讯是吗?。
  66. 线程和进程,为什么选择线程?线程为什么占用更少的资源?线程共享进程的哪些资源?线程池如何实现的?是不是什么都用线程比较好?
  67. 画一下Arm的体系架构
  68. 以下图片是哪种语言
  69. typedef struct _MAD_SYS_CONFIG{ MAD_U32 smiBase,…}MAD_SYS_CONFIG_t;
    typedef struct {MAD_U32 smiBase,…} MAD_SYS_CONFIG; 这两种写法是一个意思吗?
  70. 关注过哪些开源的东西?
  71. 内核定时器如何实现(通过链表)?如何找到具体的链表?
  72. 内核链表为什么具有通用性?
  73. 网盘妙传功能如何实现?
  74. 用户态和内核态通信方式?
  75. 分配内存哪些函数?kmalloc有两个参数,各个作用是什么?
  76. 有哪些锁,各自的效率问题?自选锁怎样实现的?
  77. 孤儿进程与僵尸进程[总结]和守护进程如何实现?
  78. 第三个项目是如何处理并发的,除了线程池还有更好的哪些方法?
  79. 主线程如何知道子线程的退出?
  80. 讲解下内核网络体系?
  81. 软中断是如何实现的?
  82. 对内存管理有什么看法和了解?
  83. 哈希表原理?针对字符串,如何确定key值(hash表存储字符串时,key怎么确定)?map怎样实现的?map和哈西表不一样吧?Hash和B树的区别?
  84. 接触过哪些STL容器?哪个效率最高?
  85. 写驱动的时候有没有遇到问题,怎么检查?有没有遇到coredump?
  86. 应用程序如果运行时出现错误该怎么排查;如果越界该怎么排查?
  87. open和fopen有什么区别?read/write和fread/fwrite区别?
  88. 线程池如何使用创建的?让你自己写一个线程池怎么实现?
  89. 主线程如何检测一个子线程也就是客户端的退出?如果现在让你实现可以浏览文件夹里文件再传输,你会怎么做?

二、HR面试题

1、中科创达HR面

1. 自我介绍下。被打断【她说不好意思注意回说谢谢,同时还要记得自己说到哪里】然后再次打断她没有让你继续自我介绍。到此自我介绍便结束。
2. 你家在哪,这些项目都是你做的吗?有没有让自己感到很挫败的事情?同学周围的人对你是怎么评价的?你的缺点是什么?【老掉牙的问题】
3. 分配任务,你和另外一个人合作,主要都是你做的,但是上级不知道,把功劳主要分给了另个人,你会怎么想。我首先讲了自己学习到的很多,并不会太在意!然后她追问:如果一直出现这个问题,你会怎么样。【先软后硬】
4. 分配一个任务,由你和另外一个人完成,你只能借助他完成,因为其能力比你强,如果他和你格格不入,你会怎么办?如果一直这样你会怎么办?【先自身后他人,结合团体公司利益阐述,最后可上升到公司层面
5. 我们公司有两种,一个是个人负责项目,成就感更好,一个是和同事一起做项目,你倾向于哪种?我说:可以和能力高于我的一起合作,并没有特定要求个人自己做。追问:如果有人能力不行怎么办?我说:没有关系,可以带。追问:不是托你后腿吗。我说:教同事,能提高自己,给予会带来回报,而且自己会的并不算真正会,把别人教会了才算。【注意这里的陷阱,一定要选择团队项目

2、中兴HR面

1. 你是如何完成一个分配给你的任务的?
2. 在你做的这些项目中有没有很难忘的困难或者经历,那你有没有想过,如果现在回想这个困难如何更好地去解决?【考察你的即时总结和部分记忆力的能力+真实性考察】
3. 这些项目都比较闲散,和真正工作的时候不一样,不能这块没有做好放一段时间,那你怎么办?【实战和训练的区别,可自由发挥】

  • 13
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
面试上,被问及关于camera驱动问题时,我们可以从以下几个方面进行回答: 首先,我们可以介绍camera驱动的作用和功能。camera驱动是用于控制和管理摄像头设备的软件模块,它负责与硬件交互,从而实现摄像头的各项功能,如捕捉图像、调整摄像头参数、控制摄像头光圈等。 其次,我们可以谈谈camera驱动的架构。一个典型的camera驱动通常由若干个组成部分组成,包括设备驱动层、总线驱动层和用户接口层。设备驱动层负责与硬件设备进行通信,总线驱动层负责处理与总线的通信,用户接口层则是供应用程序调用的API。 接着,我们可以谈谈在开发camera驱动时可能遇到的挑战和解决方案。例如,硬件设备的特性和规格多种多样,需要根据具体情况编写相应的驱动代码;不同的操作系统平台可能有不同的驱动模型,需要对平台进行兼容性适配;同时,性能和功耗也是需要考虑的重要因素。为了解决这些问题,我们需要深入了解硬件设备和操作系统的特性,并且具备良好的调试和优化能力。 最后,我们可以提到camera驱动的相关技术和标准。如V4L2(Video for Linux 2)是一套用于摄像头驱动的标准接口,它提供了在Linux系统上进行视频采集和处理的API;此外,还有一些图像处理算法和技术,如降噪、去燥、图像增强等,可以进一步提高摄像头的图像质量和性能。 总而言之,面试提问关于camera驱动问题,我们可以从摄像头驱动的作用、架构、挑战和解决方案,以及相关技术和标准等方面进行回答。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天糊土

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值