linux驱动编程基础

内存操作

kmalloc()/kfree()

vmalloc()/vfree()

vmalloc和kmalloc都用于内核中内存的分配。

vmalloc分配的为虚拟上连续的内存,kmalloc分配的是物理地址一一映射过来的连续内存。

vmalloc可申请大内存,但速度慢。kmalloc最大能分配32页(32*4K=128K)内存,速度快。

copy_from_user()

copy_to_user()

这两个函数用于用户空间和内核空间的切换,常用语ioctrl函数中实现内核态和用户态之间的数据传输。例如这个函数中传输一个指针时,需要用这两个函数才能访问到实际的数据。


任务调度
tasklet、软中断、任务队列。
tasklet、软中断运行在中断上下文中,所以不能睡眠。任务队列运行在进程上下文,可以睡眠。
tasklet基于软中断实现,都是等待内核调度执行,且都不能被中断(硬件中断除外)。软中断可以并发,tasklet不可以。
软中断是静态分配的,编译后不可改变,tasklet可在运行时改变,更加灵活。tasklet只能串行执行。
工作队列可延后执行,可睡眠,具有更大的灵活性。
定时器
硬件定时器可实现高精度的定时操作,硬件定时器会产生硬件中断。软件定时器包括timer_list和hrtimer,软件定时器用于定时触发任务,运行在进程上下文,跟上面任务调度的应用场景不同。
另外对于硬件io的一些操作还可通过pwm实现输出不同的波形。

同步技术
内核驱动开发中常用的同步机制为自旋锁和信号量。
自旋锁是短时间内进行轻量级的锁定,自旋锁能够在中断上下文中使用,不允许任务睡眠。
信号量是一种睡眠锁,即一个任务视图获得信号量时,任务会睡眠等待信号量资源。信号量适用于锁被长时间持有的情况,不可在中断上下文中使用。
当代码持有信号量时,不可以再持有自旋锁。
自旋锁会关闭内核抢占,可有效防止多处理器的并发访问。信号量代码可以被抢占。

驱动资源申请使用
linux驱动框架中存在诸多子系统,在使用资源时应尽量避免直接操作寄存器,而是优先使用框架提供的资源函数。
Gpio设置(gpio_requestgpio_get_valuegpio_set_value….)
Adc调用(adc_requestadc_requestadc_get_dataadc_start….)
Pwm调用(pwm_requestpwm_configpwm_enablepwm_disablepwm_free)

中断控制
linux中断机制分为上半部和下半部(wince也是):
linux驱动编程基础
通过request_irq申请注册中断(中断号),在中断处理函数中实现顶半部,顶半部主要调用上面讲的任务调度方法(tasklet、软中断、工作队列),在任务调度方法中实现下半部操作。