资讯详情

Linux 驱动面试题总结【转】

本文转载:http://zkread.com/article/872291.html

:字符设备是一种可以像字节流(类似文件)一样访问的设备,由字符设备驱动程序来实现这一特性。字符设备驱动程序通常至少实现open,close,read和write系统调用。典型的字符设备是字符终端、串口、鼠标、键盘、摄像头、声卡符设备。

:类似于字符设备,块设备也是通过/dev访问目录下的文件系统节点。文件系统可容纳在块设备上,如:u盘,SD卡、磁盘等。

字符设备和块设备之间的区别只在于核心内部管理数据的方式,即核心和驱动程序之间的软件接口,这对用户是透明的。在核心中,块驱动程序与字符驱动程序完全不同。

1) 查看驱动模块中打印信息的命令:

2) 使用查看字符设备信息,lsmod可以查看模块的依赖关系,modprobe其他依赖模块将在加载模块时加载。

3) 显示当前使用的中断号cat /proc/interrupt3、Linux引入模块机制有什么好处?

首先,模块是提前注册自己为未来服务的请求,然后他的初始化函数立即结束。换句话说,

好处:

1)无论资源的释放或其他清除工作如何,应用程序都可以退出,但模块的退出函数必须仔细取消初始化函数所做的一切。

2)该机制有助于缩短模块的开发周期。即:注册和卸载非常灵活方便。

由于内核空间和用户空间不能相互访问,如果需要访问,必须使用内核函数读写数据。copy_to_user():从核心空间复制到用户空间,copy_from_user():复制用户空间到核心空间。。当然,如果ioctl这两个函数如果不复制内存数据,就不会使用。

1)主设备号:主设备号标识设备对应的驱动程序。虽然现代linux内核允许多个驱动程序共享主设备号,但我们看到的大多数设备仍然按照一个主设备对应一个驱动程序的原则组织。

二次设备号:二次设备号用于正确确定设备文件所指的设备。依靠驱动程序的编写,我们可以通过二次设备号获得指向内核设备的直接指针,也可以将该设备号作为设备本地数组的索引。

2)chartest 由驱动程序4管理,本文件所称设备为64号设备。(感觉类似于串口终端或字符设备终端)。

有两种方法可以驱动注册字符设备:

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结构)。对于

是一种无须CPU使用外设与系统内存之间的双向数据传输硬件机制DMA可以使系统CPU从实际的I/O在数据传输过程中,大大提高了系统的吞吐率.

是指CPU在执行程序的过程中,一些紧急情况CPU必须暂停执行当前程序,转移处理突发事件,处理后CPU返回源程序中断并继续执行的位置。

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

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);

释放中断和中断信号线

。一切都是两面性的,所以不能简单地说效率高。如果是请求设备,请求频繁cpu对于有大量数据请求的设备或网络设备,轮询的效率高于中断。如果是一般设备,设备请求cpu如果频率较低,则中断效率较高。主要取决于请求频率。

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

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

在发送过程中不能中断,在发送过程中,不关闭中断,如果有中断,那么cpu如果中断需要重写的数据是发送数据的缓冲区,则缓冲区将被重写,即使cpu中断后,发送数据,接收方不知道数据不能接收。

在接收数据时,由于及时接收到的数据,需要打开中断。如果中断被关闭,接收方可能无法接收数据,因为相应的优先级高中断。

sk_buff结构很重要,它的意思是,用于在linux在网络子系统中的盖层之间传输数据。

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

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

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

      ,把能放在后半段(tasklet,等待队列等)的任务尽量放在后半段。

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

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

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

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

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

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

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

        第二句话的意思是:

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

   if(flag == 0)  {        flag = 1;       操作临界区;      flag = 0;   }

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

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

        因为内核没有办法直接访问物理内存地址,必须先

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

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

         Kmalloc()   __get_free_page()  mempool_create()  

int *a;char *b;a 和 b本身是什么类型?

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

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

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

两种方式

struct tasklet_struct tlet;

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

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

tasklet_schedule(&tlet);

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

【tasklet 和定期器的区别】

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

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

,所以一个时刻只有一个线程允许存在于临界区中。这点可以应用在多处理机器、或运行在单处理器上的中需要的锁定服务。

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

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

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

       

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

b)都是一个sock结构体。

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

d)都具有缓冲机制。

 

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

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

标签: fn7325力传感器fn3060力传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台