Linux driver interview questions

1. What is the main difference between character devices and block devices in Linux devices? Please list some actual devices and say which category of devices they belong to.

    Character device : A character device is a device that can be accessed like a byte stream (similar to a file), and the character device driver implements this feature. Character device drivers usually implement at least the open, close, read and write system calls. Character terminals, serial ports, mice, keyboards, cameras, sound cards and graphics cards are typical character devices.

    Block devices : Similar to character devices, block devices are also accessed through file system nodes in the /dev directory. Block devices can accommodate file systems, such as: U disk, SD card, disk, etc.

    The difference between character devices and block devices is only in the way the kernel manages data internally, that is, the software interface between the kernel and the driver, and these differences are transparent to the user. In the kernel, block drivers have a completely different interface than character drivers.

 

2. What command should be used to view the print information in the driver module? How to view information about character devices already in the kernel? How can I see which interrupt numbers are in use?

1) The command to view the print information in the driver module: dmesg

2) To view character device information, you can use lsmod and modprobe , lsmod can view the dependencies of modules, and modprobe will load other dependent modules when loading modules.

3) Display the currently used interrupt number cat /proc/interrupt


3. What are the benefits of introducing the module mechanism in Linux?

       First, the module pre-registers itself to serve a future request, and then its initialization function ends immediately. In other words, the task of the module initialization function is to prepare in advance for calling the function later .

benefit:

1) When the application exits, it can ignore the release of resources or other clearing work, but the exit function of the module must carefully undo everything done by the initialization function.

2) This mechanism helps to shorten the development cycle of the module. That is: registration and uninstallation are very flexible and convenient.

 

4. What functions are copy_to_user() and copy_from_user() mainly used for? Which functions are generally used in the file_operations structure?

      Since kernel space and user space cannot access each other , if access is required, data reading and writing must be performed with the help of kernel functions. copy_to_user(): completes the copy from kernel space to user space, copy_from_user(): completes the copy from user space to kernel space. It is generally used for the functions of memory data exchange such as read, write, and ioctl in the file_operations structure . Of course, if the ioctl does not use memory data copying, then these two functions will not be used.

 

5. Please briefly describe the purpose of the major device number and the minor device number. If you execute mknod chartest c 4 64, the chartest device is created. Please analyze which type of device driver chartest uses.

1) Major device number: The major device number identifies the driver corresponding to the device. While modern linux kernels allow multiple drivers to share major numbers, most of the devices we look at are still organized according to the "one major for one driver" principle.

   Minor number: The minor number is used by the kernel to correctly determine which device a device file refers to. Depending on how the driver is written, we can obtain a direct pointer to a kernel device through the minor device number, or we can use the device number as an index into a device-local array.

2) chartest is managed by driver 4, and the device referred to by this file is device 64. (It feels similar to a serial terminal or a character device terminal).


6. How to register a character device in the device driver? Explain the meaning of its several parameters respectively.

There are two ways to register a character device driver:

1) void cdev_init(struct cdev *cdev, struct file_operations *fops)

该注册函数可以将cdev结构嵌入到自己的设备特定的结构中。cdev是一个指向结构体cdev的指针,而fops是指向一个类似于file_operations结构(可以是file_operations结构,但不限于该结构)的指针.

2) int register_chrdev(unsigned int major, const char *namem , struct file)operations *fopen);

该注册函数是早期的注册函数,major是设备的主设备号,name是驱动程序的名称,而fops是默认的file_operations结构(这是只限于file_operations结构)。对于register_chrdev的调用将为给定的主设备号注册0-255作为次设备号,并为每个设备建立一个对应的默认cdev结构

 

7、请简述中断于DMA的区别。Linux设备驱动程序中,使用哪个函数注册和注销中断处理程序?

1)DMA:是一种无须CPU的参与就可以让外设与系统内存之间进行双向数据传输的硬件机制,使用DMA可以使系统CPU从实际的I/O数据传输过程中摆脱出来,从而大大提高系统的吞吐率.

      中断:是指CPU在执行程序的过程中,出现了某些突发事件时CPU必须暂停执行当前的程序,转去处理突发事件,处理完毕后CPU又返回源程序被中断的位置并继续执行。

     所以中断和DMA的区别就是DMA不需CPU参与而中断是需要CPU参与的

 

2)中断注册函数和中断注销函数

注册中断:

int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *dev_name, void *dev_id);

参数意义依次是:中断号,中断处理函数,中断管理有关的掩码,中断请求设备名,中断信号线。

过程是:dev_name设备请求中断->cpu分配中断号->设置中断管理的掩码->分配中断信号线->处理中断函数->完成之后再根据设置情况返回原处理程序处继续处理程序。

注销中断

Void free_irq(unsigned int irq, void *dev_id);

释放中断和中断信号线

 

8、中断和轮询哪个效率高?怎样决定是采用中断方式还是采用轮询方式去实现驱动?

     中断是CPU处于被动状态下来接受设备的信号,而轮询是CPU主动去查询该设备是否有请求。凡事都是两面性,所以,看效率不能简单的说那个效率高。如果是请求设备是一个频繁请求cpu的设备,或者有大量数据请求的网络设备,那么轮询的效率是比中断高。如果是一般设备,并且该设备请求cpu的频率比较底,则用中断效率要高一些。主要是看请求频率

 

9、简单描述在cs8900的驱动设计中, 发送数据frame和接收数据frame的过程。

1)发送流程如下:

(1) 网络设备驱动程序从上层协议传递过来的sk_buff参数获得数据包的有效数据和长度,将有效数据放入临时缓冲区。
(2) 对于以太网,如果有效数据的长度小于以太网冲突检测所要求的数据桢的最小长度,则给临时缓冲区的末尾填充0
(3) 设置硬件寄存器,驱使网络设备进行数据发送操作。

2)接收流程

   网络设备接收数据主要是由中断引发设备的中断处理函数,中断处理函数判断中断类型,如果为接收中断,则读取接受到的数据,分配sk_buff数据结构和数据缓冲区,将接收到的数据复制到数据缓冲区,并调用netif_rx()函数将sk_buff传递给上层协议。


10、Cs8900.c的驱动中,发送数据frame的过程为什么需要关中断?接收数据frame的过程为什么不需要关中断?

       在发送过程中是不能被打断的,在发送的过程中,不关中断,这时候如果有一个中断到来,那么cpu有可能会去相应该中断,如果该中断需要改写的数据是发送数据的缓冲区,那么缓冲区将被改写,这样即使cpu相应完毕该中断,再发送数据,接收方也不认识该数据不能接收。

      在接收数据的时候,需要打开中断,是因为要及时的相应接收到的数据。如果关闭该中断,那么接收方有可能因为相应优先级高的中断而接收不到该数据。

 

11、简单描述skbuff这个数据结构在网络结构中所起到的作用,为什么需要一个skbuff,它的分配和释放主要都在什么部位

        sk_buff结构非常重要,它的含义为“套接字缓冲区”,用于在linux网络子系统中的盖层之间传递数据。

当发送数据包时,linux内核的网络处理模块必须建立一个包含要传输的数据包的sk_buff,然后将sk_buff递交给下层,各层在sk_buff中添加不同的协议头直至交给网络设备发送。同样的,当网络设备从网络媒介上接受到数据包后,它必须将接受到的数据转换为sk_buff数据结构并传递给上层,盖层不抛去相应的协议头直至交给用户。分配sk_buff在接受一开始就应该分配,在发送完毕数据之后可以释放sk_buff

 

12、字符型驱动设备怎么创建设备文件

        手动创建:mknod /dev/led c 250 0    其中dev/led 为设备节点 c 代表字符设备 250代表主设备号 0代表次设备号

       还有UDEV/MDEV自动创建设备文件的方式,UDEV/MDEV是运行在用户态的程序,可以动态管理设备文件,包括创建和删除设备文件,运行在用户态意味着系统要运行之后。在  /etc/init.d/rcS 脚本文件中会执行mdev -s 自动创建设备节点。

 

13、写一个中断服务需要注意哪些?如果中断产生之后要做比较多的事情你是怎么做的?

      中断处理例程应该尽量短,把能放在后半段(tasklet,等待队列等)的任务尽量放在后半段。

     写一个中断服务程序要注意快进快出,在中断服务程序里面尽量快速采集信息,包括硬件信息,然后退出中断,要做其它事情可以使用工作队列或者tasklet方式。也就是中断上半部和下半部。

第二:中断服务程序中不能有阻塞操作。应为中断期间是完全占用CPU的(即不存在内核调度),中断被阻塞住,其他进程将无法操作;

第三:中断服务程序注意返回值,要用操作系统定义的宏做为返回值,而不是自己定义的OK,FAIL之类的。

 

14、自旋锁和信号量在互斥使用时需要注意哪些?在中断服务程序里面的互斥是使用自旋锁还是信号量?还是两者都能用?为什么?

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

      中断服务例程中的互斥使用的是自旋锁,原因是在中断处理例程中,硬中断是关闭的;但是要注意这样会丢失可能到来的中断。

 

15、原子操作你怎么理解?为了实现一个互斥,自己定义一个变量作为标记来作为一个资源只有一个使用者行不行?

        原子操作指的是无法被打断的操作。

        第二句话的意思是:

  定义一个变量,比如 int flag =0;

   if(flag == 0)
  {
       flag = 1;


       操作临界区;
      flag = 0;
   }

 

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

        insmod调用init函数,rmmod调用exit函数。这两个函数在设计时要注意什么?卸载模块时曾出现卸载失败的情形,原因是存在进程正在使用模块,检查代码后发现产生了死锁的问题。

      要注意在init函数中申请的资源在exit函数中要释放,包括存储,ioremap,定时器,工作队列等等。也就是一个模块注册进内核,退出内核时要清理所带来的影响,带走一切不留下一点痕迹。

 

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

        因为内核没有办法直接访问物理内存地址,必须先通过ioremap获得对应的虚拟地址

 

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

         设备驱动模型三个重要成员是 总线、设备、驱动;

         platfoem总线的匹配规则是:要匹配的设备和驱动都要注册;

 

19、linux内核里面,内存申请有哪几个函数,各自的区别?

         Kmalloc()   __get_free_page()  mempool_create()  

 

20、 IRQ和FIQ有什么区别,在CPU里面是是怎么做的


21

int *a;
char *b;

a 和 b本身是什么类型?

a、b里面本身存放的只是一个地址,难道是这两个地址有不同么?


22、 中断的上半部分和下半部分的问题:讲下分成上半部分和下半部分的原因,为何要分?讲下如何实现?

         上半部分执行与硬件相关的处理要求快, 而有些驱动在中断处理程序中又需要完成大量工作,这构成矛盾,所以Linux有所谓的bottom half机制,中断处理程序中所有不要求立即完成的,在开中断的环境下,由底半程序随后完成.

         Linux的底半处理实际上是建立在内核的软中断机制上的.如何实现该机制?

两种方式

【tasklet  工作队列】

1.定义和初始化

struct tasklet_struct tlet;

tasklet_init(&tlet, jit_tasklet_fn, (unsigned long) data);
参数
第一个:定义的tasklet变量
第二个:函数
第三个:数据  传递给回调函数的数据

2. 定义函数

void jit_tasklet_fn(unsigned long arg)
{
//中断的底半部 执行该函数的时候,已经出中断了
printk("in jit_tasklet_fn  jiffies=%ld\n",jiffies);
}

3. 在需要调度的地方调用以下函数

tasklet_schedule(&tlet);

   一般在中断函数当中调度在不晚于下一个时钟滴答之前执行


【tasklet 和定期器的区别】

1. 执行时间

定时器的执行:时间是确定的
tasklet       :不确定的

2.tasklet 执行耗时的操作的

 

23、内核函数mmap的实现原理,机制?

         mmap函数实现把一个文件映射到一个内存区域,从而我们可以像读写内存一样读写文件,他比单纯调用read/write也要快上许多。在某些时候我们可以把内存的内容拷贝到一个文件中实现内存备份,当然,也可以把文件的内容映射到内存来恢复某些服务。另外,mmap实现共享内存也是其主要应用之一,mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存

 

24、驱动里面为什么要有并发、互斥的控制?如何实现?讲个例子?

 

25、spinlock自旋锁是如何实现的?

       自旋锁在同一时刻只能被最多一个内核任务持有,所以一个时刻只有一个线程允许存在于临界区中。这点可以应用在多处理机器、或运行在单处理器上的抢占式内核中需要的锁定服务。



26、信号量简介

        这里也介绍下信号量的概念,因为它的用法和自旋锁有相似的地方。

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

 

27、 任务调度的机制?

 

28、什么是GPIO?

         general purpose input/output  

         GPIO是相对于芯片本身而言的,如某个管脚是芯片的GPIO脚,则该脚可作为输入或输出高或低电平使用,当然某个脚具有复用的功能,即可做GPIO也可做其他用途。 也就是说你可以把这些引脚拿来用作任何一般用途的输入输出,例如用一根引脚连到led的一极来控制它的亮灭,也可以用一根(一些)引脚连到一个传感器上以获得该传感器的状态,这给cpu提供了一个方便的控制周边设备的途经。如果没有足够多的gpio管脚,在控制一些外围设备时就会力有不逮,这时可采取的方案是使用CPLD来帮助管理。

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

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

 

30、LINUX下的Socket套接字和Windows下的WinSock有什么共同点?请从C/C++语言

a)都基于TCP/IP协议,都提供了面向连接的TCP SOCK和无连接的UDP SOCK。

b)都是一个sock结构体。

c)都是使用sock文件句柄进行访问。

d)都具有缓冲机制。

                
31、一个计划跑LINUX系统的ARM系统把bootloader烧录进去后,上电后串口上没有任何输出,硬件和软件各应该去检查什么?  
 

 提示: 1.跑LINUX的系统一般都需要外扩DRAM,一般的系统也经常有NOR或NAND FLASH          

        bootloader一般是由汇编和C编写的裸奔程序[5分]

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325370714&siteId=291194637