嵌入式linux面试遇到的几个问题

 

  [纵目科技/飞凌科技]

1、驱动里为什么要有并发、互斥的控制?

         内核中的很多事情是需要多线程、多进程来实现的,并发(concurrency)指的是多个执行单元同时、并行被执行,而并发的执行单元对共 享资源(硬件资源和软件上的全局变量、静态变量等)的访问则很容易导致竞态(race conditions)。

       解决竞态问题的途径是保证对共享资源的互斥访问,所谓互斥访问就是指一个执行单元 在访问共享资源的时候,其他的执行单元都被禁止访问。

      访问共享资源的代码区域被称为临界区,临界区需要以某种互斥机 制加以保护,中断屏蔽,原子操作,自旋锁,和信号量都是linux设备驱动中可采用的互斥途径。

2、有几种情况会导致竟态的发生?

  1.  对称多处理器(SMP)多个CPU,使用共同的系统总线,因此可访问共同的外设和存储器。
  2.  单CPU内进程与抢占它的进程     [进程与进程]
  3.  中断(硬中断、软中断、Tasklet、底半部)与进程之间  [进程与中断]
  4.  中断与中断 (中断被更高优先级的中断打断)

只要并发的多个执行单元存在对共享资源的访问,竞态就有可能发生。
如果中断处理程序访问进程正在访问的资源,则竞态也会会发生。
多个中断之间本身也可能引起并发而导致竞态(中断被更高优先级的中断打断)。

 

3、有几种方法来保护临界资源?他们的区别是什么?

1.中断屏蔽

2.原子操作----->进程与进程 (原子操作不能被中断打破。)

3.自旋锁 ----> SMP (自旋锁就是忙等锁、可能导致系统死锁、不能调用引起进程调度的函数)

4. 信号量------->进程与进程 , 进程与中断

(休眠锁(可以在自己允许的情况下,让多个进程访问自己的资源、可休眠)

工作中 ioctl 常加自旋锁,保护资源,LED要灭就灭,要亮就亮。

因为你不知道,有几个进程或线程在调用这个设备的ioctl

 

 

4、用户态如何保护临界资源,有几种方法,区别是什么?

互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排他性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况下允许多个访问者同时访问资源。

     互斥锁 mutex 

     信号量 

互斥锁用于线程的互斥,信号量用于线程的同步。

一个互斥锁只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题

信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量时,也可以完成一个资源的互斥访问。

 

5、如何理解中断的上半部和下半部?(飞凌科技)


上半部的功能是响应中断。(响应的过程中不能被中断)------》 很快。

下半部的功能是处理比较复杂的过程。(可被中断),一般通过软中断 ,tasklet,和工作队列来实现的.

 

6、如何理解中断底半部?


三种方式来实现:软中断、tasklet 、workqueue

软中断: 在内核中不推荐(异常)

tasklet:运行在中断上下文,不能有长的延时函数(不需要睡眠的时候用)

workqueue :运行在进程上下文,可以有长延时函数(需要睡眠的时候用)

工作队列(work queue)是另外一种将工作推后执行的形式,它和前面讨论的tasklet有所不同。工作队列可以把工作推后,交由一个内核线程去执行,也就是说,这个下半部分可以在进程上下文中执行。这样,通过工作队列执行的代码能占尽进程上下文的所有优势。最重要的就是工作队列允许被重新调度甚至是睡眠。

 

7、什么中断上下文?什么是进程上下文?


进程上下文:(用户态和内核态切换)

(1)进程上文:其是指进程由用户态切换到内核态是需要保存用户态时cpu寄存器中的值,进程状态以及堆栈上的内容,即保存当前进程的进程上下文,以便再次执行该进程时,能够恢复切换时的状态,继续执行。

(2)进程下文:其是指切换到内核态后执行的程序,即进程运行在内核空间的部分。

一个程序执行了系统调用或者触发某个异常(软中断),此时就会陷入内核空间,内核此时代表进程执行,并处于进程上下文中。

中断上下文:(内核态和硬件)

(1)中断上文:硬件通过中断触发信号,导致内核调用中断处理程序,进入内核空间。中断上文可以(主要是当前被中断的进程环境,要被保存,方便恢复)

(2)中断下文:执行在内核空间的中断服务程序。

 程序在执行过程中通常有用户态和内核态两种状态,CPU对处于内核态根据上下文环境进一步细分,因此有了下面三种状态:

(1)内核态,运行于进程上下文,内核代表进程运行于内核空间。

(2)内核态,运行于中断上下文,内核代表硬件运行于内核空间。

(3)用户态,运行于用户空间。

 

8、驱动中常用的申请内存的函数?都有什么区别?

kmalloc()、kzalloc()、vmalloc() 的共同特点是:

  1. 用于申请内核空间的内存;
  2. 内存以字节为单位进行分配;
  3. 所分配的内存虚拟地址上连续;

kmalloc()、kzalloc()、vmalloc() 的区别是:

  1. kzalloc 是强制清零的 kmalloc 操作;(以下描述不区分 kmalloc 和 kzalloc)
  2. kmalloc 分配的内存大小有限制(128KB),而 vmalloc 没有限制;
  3. kmalloc 可以保证分配的内存物理地址是连续的,但是 vmalloc 不能保证;
  4. kmalloc 分配内存的过程可以是原子过程(使用 GFP_ATOMIC),而 vmalloc 分配内存时则可能产生阻塞;
  5. kmalloc 分配内存的开销小,因此 kmalloc 比 vmalloc 要快;

一般情况下,内存只有在要被 DMA 访问的时候才需要物理上连续,但为了性能上的考虑,内核中一般使用 kmalloc(),而只有在需要获得大块内存时才使用 vmalloc()。例如,当模块被动态加载到内核当中时,就把模块装载到由 vmalloc() 分配的内存上。

 

 

9、同一个进程可以在两个核上跑吗

  能不能跑,要看 cache 的一致性。我们知道 在CPU与memory 之间,有一个 cache。 CPU访问一个数据的时候,如果被cache命中的话,

CPU就会很快的读取出数据,这个速度远大于从 memory 中读取的数据。如果一个CPU有多个核,要看这几个核是不是共享cache。共享cache还好。

  cpu  <--->  cache  <---> memory

如果不是共享cache,那就保持cache的一致性,但也是有专门的协议来保证的,比如MESI等。

cache的不一致,是因为同样一份数据在多个cache中存在多份拷贝,如果数据在一个cache中被写另一个cache却不知道,就会有不一致。对于多核共享cache最基本的方法就是写失效和写更新两种。每个核的专有cache要时刻监听总线上的写cache请求,一旦监听到总线要写的cache块自己肚子里也有,就将自己肚子里的cache块置为失效(写失效),等到下次该块cache miss再重新load最新的数据。或者在总线更新某块的时候,刚好自己肚子里也有一份该块的拷贝,顺便把自己内部的cache块也更新了(写更新),就可以保证自己一直是最新的数据。
从硬件原理上来讲,主要就是做到写操作即时即刻的传递给所有的核/cache。写操作一定要广播出去,只要通知到位,就有办法。

 

 

 

 

 

 

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值