linux字符驱动之初见

来源:互联网 发布:光电效应实验报告数据 编辑:程序博客网 时间:2024/05/22 08:03

学习驱动也有长达一年多的时间了,受益最深的就是看韦东山老师的视频,如今已经几乎将二期三期的视频全部看完,甚至已经将二期视频看过好几遍,为了再次加深印象,我将韦老师的源码自己全部编写一遍。将所有遇到的问题,记录在此。觉得看了韦老师的视频,再看其他视频都是弱爆了。由于是文章记录,不可能写的非常详细,只摘录关键点,想具体详细的深入,还请去看韦老大的视频吧。

这篇文章是主要是讲解字符驱动的框架,并没有涉及高级字符驱动。

一、字符驱动框架

------------------------------------------------------------------------

APP:     open               read                   write

------------------------------------------------------------------------

C 库

------------------------------------------------------------------------

      system_open    system_read       system_write


------------------------------------------------------------------------

KERNEL:

      led_open           led_read               led_wirte

------------------------------------------------------------------------


问:应用程序open如何找到驱动程序的open函数

答:应用程序的open通过C库的open函数,通过系统调用的system_open函数,进而通过swi val指令,进入内核,通过一定的办法来找到驱动程序的open函数。

问:通过什么样的方法来找到驱动程序的open函数

答:通过一个注册函数+设备节点

注册函数如下(旧的注册函数,新的以后再说):

register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)

参数1:主设备号(重要)

参数2:名字(不重要)

参数3:file_operations结构体(重要)

设备节点:

可以手工创建也可以自动创建,这里暂且只说手工创建

mknod  /dev/xxx  c  252  0

具体什么含义,我就不多说了,看视频吧,很简单。


问:应用程序一般是由main函数开始执行,那么驱动程序一般是先执行什么?

答:通过一个宏,指定驱动程序的入口函数,当装载驱动时就会执行入口函数。

例如:module_init(first_drv_init);  //用于修饰入口函数

自然地,驱动程序的出口函数,则是在卸载驱动时就会执行出口函数。

例如:module_exit(first_drv_exit);  //用于修饰出口函数


驱动源程序如下:

#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>#include <linux/module.h>int major;static int first_drv_open(struct inode * inode, struct file * filp){printk("first_drv_open\n");return 0;}static int first_drv_write(struct file * file, const char __user * buffer, size_t count, loff_t * ppos){printk("first_drv_write\n");return 0;}/* File operations struct for character device */static const struct file_operations first_drv_fops = {.owner= THIS_MODULE,.open= first_drv_open,.write      = first_drv_write,};/* 驱动入口函数 */static int first_drv_init(void){/* 主设备号设置为0表示由系统自动分配主设备号 */major = register_chrdev(0, "first_drv", &first_drv_fops);return 0;}/* 驱动出口函数 */static void first_drv_exit(void){unregister_chrdev(major, "first_drv");}module_init(first_drv_init);  //用于修饰入口函数module_exit(first_drv_exit);  //用于修饰出口函数MODULE_AUTHOR("LWJ");MODULE_DESCRIPTION("Just for Demon");MODULE_LICENSE("GPL");  //遵循GPL协议

Makefile源码如下:

KERN_DIR = ~/work/s3c2440/linux/kernel/linux-2.6.22.6all:make -C $(KERN_DIR) M=`pwd` modules clean:make -C $(KERN_DIR) M=`pwd` modules cleanrm -rf modules.orderobj-m+= first_drv.o

测试程序如下

#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>int main(void){int fd;int val = 1;fd = open("/dev/xxx",O_RDWR);if(fd < 0){printf("open error\n");}write(fd,&val,4);return 0;}


编译:arm-linux-gcc first_test.c -omain

测试:insmod first_drv.ko
发现:多了一个first_drv的节点

cat /proc/devices
Character devices:

....
252 first_drv
...
这时候直接调用驱动测试程序main,发现报错

# /mnt/s3c2440/linux/driver/net/1/main
open error

解决方法解释上面的mknod /dev/xxx c 252 0,此就是创建一个主设备好252,次设备号0的设备节点
然后调用main,会提示

# /mnt/s3c2440/linux/driver/net/1/main
first_drv_open
first_drv_write

根据http://blog.csdn.net/lwj103862095/article/details/17468587测试验证修改


原创粉丝点击