Linux添加设备驱动步骤和实例
2012-06-09 16:25
661 查看
在系统内部,I/O设备等等存取通过一组固定的入口点来进行,这组入口点由每个
设备的设备驱动程序提供。在Linux系统里,设备驱动程序提供的入口点由一个结构来向系统进行说明,此结构体定义为:
Structfile_operations{
int (*lseek)(struct innode *innode, structfile *file,off_t off, int pos);
/*移动文件指针的位置*/
int (*read)(struct innode *innode, structfile *file, char *buf, int count);
/*读操作,buf为存放读取结果的缓冲区,count为要读取的数据长度*/
int (*write)(struct innode *innode, structfile *file, char *buf, int count);
/*写操作,与read类似*/
int (*readdir)(struct innode *innode, structfile *file, struct dirent *dirent, int count);
/*取得下一个目录入口点*/
int (*select)(struct innode *innode, structfile *file, int sel_type, select_table *wait);
/*检查设备,看数据是否可读或设备是否可用于写数据*/
int (*ioctl)(struct innode *innode, structfile *file, unsigned int cmd, unsigned int arg);
/*进行读写以外的其他特殊操作,参数cmd为自定义的命令*/
int (*mmap)(void)
/*把设备的内容映射到地址空间*/
int (*open)(struct innode *innode, structfile *file);
/*打开设备进行I/O操作*/
int (*release)(struct innode *innode, structfile *file);
/*关闭设备*/
}
操作步骤
①编写设备驱动程序zhangjiajie.c;
②在zhangjiajie.c同一目录下编写Makefile文件;
③ $make:编译Makefile文件,生成zhangjiajie.ko文件;
④ $insmod./zhangjiajie.ko:挂载驱动;
⑤ $cat/proc/devices:查看添加的设备的主驱动号,我的驱动号为250,如下图3所示;
⑥ $mknod/dev/zhangjiajie c 250 0:挂载设备驱动。
⑦编译测试程序,测试驱动。
file_operations*fops);
major为设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态分配一个主设备号。Name是设备名。Fops为对各个调用的入口点的说明。
返回0便是返回成功,返回-EINVAL表示申请的主设备号非法,返回-EBUSY表示说申请的主设备号正被其他设备驱动程序使用。如果动态分配主设备号成功,会返回说分配的主设备号。
如果register_chrdev成功,设备名就会出现在/proc/devices文件里。
(二) obj-m:=zhangjiajie.o
Makefile中的该语句表示最终生成模块文件,生成的模块文件名为zhangjiajie.o。
(三) Make –Cxxx M=$(shell pwd) modules
表示首先改变目录到-C指定的位置,M=选项是makefile在构造modukes目标前,返
回到模块源码目录。然后modules目标指向obj-m变量中设定的模块。
操作过程中要注意到的
① .c驱动程序文件和 .o文件名要一致;
② Makefile文件名的M要大写;
③ make时需要切换到root权限。
设备的设备驱动程序提供。在Linux系统里,设备驱动程序提供的入口点由一个结构来向系统进行说明,此结构体定义为:
Structfile_operations{
int (*lseek)(struct innode *innode, structfile *file,off_t off, int pos);
/*移动文件指针的位置*/
int (*read)(struct innode *innode, structfile *file, char *buf, int count);
/*读操作,buf为存放读取结果的缓冲区,count为要读取的数据长度*/
int (*write)(struct innode *innode, structfile *file, char *buf, int count);
/*写操作,与read类似*/
int (*readdir)(struct innode *innode, structfile *file, struct dirent *dirent, int count);
/*取得下一个目录入口点*/
int (*select)(struct innode *innode, structfile *file, int sel_type, select_table *wait);
/*检查设备,看数据是否可读或设备是否可用于写数据*/
int (*ioctl)(struct innode *innode, structfile *file, unsigned int cmd, unsigned int arg);
/*进行读写以外的其他特殊操作,参数cmd为自定义的命令*/
int (*mmap)(void)
/*把设备的内容映射到地址空间*/
int (*open)(struct innode *innode, structfile *file);
/*打开设备进行I/O操作*/
int (*release)(struct innode *innode, structfile *file);
/*关闭设备*/
}
操作步骤
①编写设备驱动程序zhangjiajie.c;
#include<linux/types.h> #include<linux/fs.h> #include<linux/mm.h> #include<linux/errno.h> #include<asm/segment.h> #include<asm/uaccess.h> unsigned int zjj_major = 0; /*buf涓哄瓨鏀捐鍙栫粨鏋滅殑缂撳啿鍖猴紝length涓鸿璇诲彇鏁版嵁鐨勯暱搴?/ static ssize_t zjj_read(struct file *file, char *buf, size_t length, loff_t *offset) { int n = 0; n = min( strlen("zhangjiajie's driver!"), length ); if( copy_to_user(buf,"zhangjiajie's driver!", n) ) { return -EFAULT; } return n; } static ssize_t zjj_write( struct file *file, const char *buf, size_t length,loff_t *offset) { return length; }
static int zjj_open(struct inode *inode, struct file *file) { printk("open file succeed\n"); return 0; } static int zjj_release(struct inode *inode, struct file *file) { printk("close file succeed\n"); return 0; } static const struct file_operations zjj_fops = { .open = zjj_open, .read = zjj_read, .write = zjj_write, .release = zjj_release, }; static int __init zjj_init(void) { zjj_major = register_chrdev(0,"ZJJ_DRIVER",&zjj_fops); if( zjj_major < 0 ) { printk("register dirver error\n"); return -1; } else{ printk("register driver %d succeed\n",zjj_major); } return 0; } static void __exit zjj_exit(void) { unregister_chrdev(zjj_major,"ZJJ_DRIVER"); printk("unistall driver succeed\n"); } module_init(zjj_init); module_exit(zjj_exit);
②在zhangjiajie.c同一目录下编写Makefile文件;
obj-m:=zhangjiajie.o KERNELBUILD:=/lib/modules/3.2.13/build default:
③ $make:编译Makefile文件,生成zhangjiajie.ko文件;
④ $insmod./zhangjiajie.ko:挂载驱动;
⑤ $cat/proc/devices:查看添加的设备的主驱动号,我的驱动号为250,如下图3所示;
⑥ $mknod/dev/zhangjiajie c 250 0:挂载设备驱动。
⑦编译测试程序,测试驱动。
#include<sys/types.h> #include<sys/stat.h> #include<fcntl.h> #include<stdio.h> int main(void) { int fd, n; char string[32]; for(n = 0; n < 32; n++){ string = ' '; } printf("Input string: "); scanf("%s",string); fd = open("/dev/ZJJ_DRIVER",O_RDWR); write(fd,string,32); read(fd,string,32); printf("from ZJJ_DRIVER: %s\n",string); return 1; }
用到的函数说明
(一)intregister_chrdev(unsigned int major, const char *name, structfile_operations*fops);
major为设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态分配一个主设备号。Name是设备名。Fops为对各个调用的入口点的说明。
返回0便是返回成功,返回-EINVAL表示申请的主设备号非法,返回-EBUSY表示说申请的主设备号正被其他设备驱动程序使用。如果动态分配主设备号成功,会返回说分配的主设备号。
如果register_chrdev成功,设备名就会出现在/proc/devices文件里。
(二) obj-m:=zhangjiajie.o
Makefile中的该语句表示最终生成模块文件,生成的模块文件名为zhangjiajie.o。
(三) Make –Cxxx M=$(shell pwd) modules
表示首先改变目录到-C指定的位置,M=选项是makefile在构造modukes目标前,返
回到模块源码目录。然后modules目标指向obj-m变量中设定的模块。
操作过程中要注意到的
① .c驱动程序文件和 .o文件名要一致;
② Makefile文件名的M要大写;
③ make时需要切换到root权限。
相关文章推荐
- linux 块设备驱动(四)——简单的sbull实例
- Linux设备驱动程序架构分析之一个I2C驱动实例
- Linux 驱动学习笔记3 -- 字符设备驱动实例(driver+client)
- linux字符设备驱动步骤
- linux网络设备应用与驱动编程学习4——模板与实例(B)——打开和释放方法
- [Linux驱动]字符设备驱动学习笔记(二)———实例
- Linux I2C设备驱动编写(三)-实例分析AM3359
- linux驱动学习--第二十一天:第十二章:Linux 字符设备驱动综合实例(一) 键盘驱动
- Linux 设备驱动开发 —— platform设备驱动应用实例解析
- linux驱动为自定义设备添加poll方法
- Linux I2C设备驱动编写(三)-实例分析AM3359
- Linux-Flash驱动(2)-块设备驱动实例分析
- 如何在linux下添加自己的设备驱动
- Linux总线设备驱动模型相关理论和实例
- Linux字符设备驱动实例
- linux字符设备驱动实例
- [Linux驱动]字符设备驱动学习笔记(二)———实例
- Linux设备驱动:kobject原理与实例分析
- Linux设备驱动之s3c2440添加LCD驱动
- 嵌入式Linux之我行——RamDisk块设备驱动实例开发讲解