今年带软件08级童鞋LinuxOS试验的时候,导师让我写一个最简单的字符设备驱动,以便让从未接触过的初学者快速入门。代码参考如下。
字符设备驱动程序:
#include < linux/init.h > #include < linux/module.h > #include < linux/types.h > #include < linux/fs.h > #include < asm/uaccess.h > #include < linux/cdev.h > MODULE_AUTHOR("Edsionte Wu"); MODULE_LICENSE("GPL"); #define MYCDEV_MAJOR 231 /*the predefined mycdev's major devno*/ #define MYCDEV_SIZE 100 static int mycdev_open(struct inode *inode, struct file *fp) { return 0; } static int mycdev_release(struct inode *inode, struct file *fp) { return 0; } static ssize_t mycdev_read(struct file *fp, char __user *buf, size_t size, loff_t *pos) { unsigned long p = *pos; unsigned int count = size; int i; char kernel_buf[MYCDEV_SIZE] = "This is mycdev!"; if(p >= MYCDEV_SIZE) return -1; if(count > MYCDEV_SIZE) count = MYCDEV_SIZE - p; if (copy_to_user(buf, kernel_buf, count) != 0) { printk("read error!\n"); return -1; } /* for (i = 0; i < count; i++) { __put_user(i, buf);//write 'i' from kernel space to user space's buf; buf++; } */ printk("edsionte's reader: %d bytes was read...\n", count); return count; } static ssize_t mycdev_write(struct file *fp, const char __user *buf, size_t size, loff_t *pos) { return size; } /*filling the mycdev's file operation interface in the struct file_operations*/ static const struct file_operations mycdev_fops = { .owner = THIS_MODULE, .read = mycdev_read, .write = mycdev_write, .open = mycdev_open, .release = mycdev_release, }; /*module loading function*/ static int __init mycdev_init(void) { int ret; printk("mycdev module is staring..\n"); ret=register_chrdev(MYCDEV_MAJOR,"edsionte_cdev",&mycdev_fops); if(ret<0) { printk("register failed..\n"); return 0; } else { printk("register success..\n"); } return 0; } /*module unloading function*/ static void __exit mycdev_exit(void) { printk("mycdev module is leaving..\n"); unregister_chrdev(MYCDEV_MAJOR,"edsionte_cdev"); } module_init(mycdev_init); module_exit(mycdev_exit);
Makefile文件:
obj-m:=mycdev.o PWD:=$(shell pwd) CUR_PATH:=$(shell uname -r) KERNEL_PATH:=/usr/src/linux-headers-$(CUR_PATH) all: make -C $(KERNEL_PATH) M=$(PWD) modules clean: make -C $(KERNEL_PATH) M=$(PWD) clean
用户态测试程序:
#include < stdio.h > #include < sys/types.h > #include < sys/stat.h > #include < fcntl.h > #include < stdlib.h > int main() { int testdev; int i, ret; char buf[15]; testdev = open("/dev/mycdev", O_RDWR); if (-1 == testdev) { printf("cannot open file.\n"); exit(1); } if (ret = read(testdev, buf, 15) < 15) { printf("read error!\n"); exit(1); } printf("%s\n", buf); close(testdev); return 0; }
使用方法:
1.make编译mycdev.c文件,并插入到内核;
2.通过cat /proc/devices 查看系统中未使用的字符设备主设备号,比如当前231未使用;
3.创建设备文件结点:sudo mknod /dev/mycdev c 231 0;具体使用方法通过man mknod命令查看;
4.修改设备文件权限:sudo chmod 777 /dev/mycdev;
5.以上成功完成后,编译本用户态测试程序;运行该程序查看结果;
6.通过dmesg查看日志信息;
您还是学生?研究生?博士?厉害啊
[回复一下]
edsionte 回复:
8月 21st, 2011 at 21:52
@钱国正, 我是在读研究生。您过奖了。。
[回复一下]
您这个网站自己掏腰包的吧,真佩服您
[回复一下]
正在看LDD第三版,2.6内核好像推荐使用register_chrdev_region和alloc_chrdev_region
[回复一下]
edsionte 回复:
11月 26th, 2011 at 21:24
@stephen, 这个是为了大家方便使用,用最简单的方法实现字符设备驱动。
之前我的文章中有关于register_chrdev_region和alloc_chrdev_region的使用介绍。
[回复一下]
你好,我是南理工的一名研一学生,我目前在学习linux,可还是个初学者,能加一下QQ吗?想向你请教点问题。我的QQ是895498069
[回复一下]
edsionte 回复:
1月 3rd, 2012 at 21:48
@袁, 发邮件吧。
[回复一下]