1) 最小框架
/* Example Minimal Character Device Driver */ #include <linux/module.h> static int __init hello_init(void) { printk("Hello Example Init/n"); return 0; } static void __exit hello_exit(void) { printk("Hello Example Exit/n"); } module_init(hello_init); module_exit(hello_exit); MODULE_AUTHOR("OOO"); MODULE_DESCRIPTION("Hello Example"); MODULE_LICENSE("GPL");
2) 增加调用接口
/* Example Minimal Character Device Driver */ #include <linux/module.h> #include <linux/fs.h> #define HELLO_MAJOR 242 static int debug_enable = 0; module_param(debug_enable, int, 0); MODULE_PARM_DESC(debug_enable, "Enable module debug mode."); struct file_operations hello_fops; static int hello_open(struct inode *inode, struct file *file) { printk("hello_open: successful/n"); return 0; } static int hello_release(struct inode *inode, struct file *file) { printk("hello_release: successful/n"); return 0; } static ssize_t hello_read(struct file *file, char *buf, size_t count, loff_t *ptr) { printk("hello_read: returning zero bytes/n"); return 0; } static ssize_t hello_write(struct file *file, const char *buf, size_t count, loff_t *ppos) { printk("hello_write: accepting zero bytes/n"); return 0; } static int hello_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { printk("hello_ioctl: cmd=%d, arg=%ld/n", cmd, arg); return 0; } static int __init hello_init(void) { int ret; printk("Hello Example Init - debug mode is %s/n", debug_enable ? "enabled" : "disabled"); ret = register_chrdev(HELLO_MAJOR, "hello", &hello_fops); if(ret < 0) { printk("Error registering hello device/n"); goto hello_fail; } printk("Hello: registered module successfully!/n"); /* Init processing here... */ return 0; hello_fail: return ret; } static void __exit hello_exit(void) { printk("Hello Exaple Exit/n"); } struct file_operations hello_fops = { owner: THIS_MODULE, read: hello_read, write: hello_write, ioctl: hello_ioctl, open: hello_open, release: hello_release, }; module_init(hello_init); module_exit(hello_exit); MODULE_DESCRIPTION("Hello Module Example"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("OOO");
在linux源码树添加相关配置文件,生成hello.ko,安装到/lib/modules
3) 测试该模块
在目标平台上,
# insmod hello.ko
创建设备节点,比如/dev/hello
# mknod /dev/hello c 242 0
然后,编写测试程序:
/* test hello.ko * you should insmod hello.ko and mknod /dev/hello before */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main(int argc, char **argv) { int fd; int rc = 0; char *rd_buf[16]; printf("%s: entered/n", argv[0]); fd = open("/dev/hello", O_RDWR); if(fd == -1) { printf("open failed"); rc = fd; exit(-1); } printf("%s: open successful: %d/n", argv[0], fd); close(fd); }
交叉编译后,bin档(比如hello-test)放到rootfs/bin目录,在目标平台上运行
# hello-test
Linux字符设备驱动开发
本文介绍了一个简单的Linux字符设备驱动程序的实现过程,包括最小框架的构建、添加调用接口及测试方法。通过实例展示了如何注册设备号、定义文件操作结构体,并提供了测试程序和步骤。
470

被折叠的 条评论
为什么被折叠?



