字符设备使用起来比较麻烦。这里笔记下最简单的使用方法。
CONTENTS
Makefile:
obj-m := hellocdev.o KERNEL_DIR := /lib/modules/$(shell uname -r)/build PWD := $(shell pwd) all: make -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules clean: rm *.o *.ko *.mod.c .PHONY:clean
hellocdev.c:
#include <linux/kernel.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/fs.h> #include <linux/cdev.h> #include <asm/uaccess.h> MODULE_LICENSE("Dual BSD/GPL"); static int default_Major = 0; static int default_Minor = 0; static int default_DevNum = 1; module_param(default_Major, int, S_IRUGO); #define BUFFER_SIZE 10 struct Hellocdev_Node_Struct { struct cdev _cdev; dev_t _devnum; char _buffer[BUFFER_SIZE]; }MyNode; int hellocdev_open(struct inode *inode, struct file *filp) { struct Hellocdev_Node_Struct *pMyNode; pMyNode = container_of(inode->i_cdev, struct Hellocdev_Node_Struct, _cdev); filp->private_data = pMyNode; printk(KERN_ALERT "hellocdev_open Called pMyNode->_buffer:%s\n", pMyNode->_buffer); return 0; } int hellocdev_release(struct inode *inode, struct file *filp) { struct Hellocdev_Node_Struct *pMyNode = filp->private_data; printk(KERN_ALERT "hellocdev_release Called pMyNode->_buffer:%s\n", pMyNode->_buffer); return 0; } ssize_t hellocdev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { struct Hellocdev_Node_Struct *pMyNode = filp->private_data; if (count >= BUFFER_SIZE) { count = BUFFER_SIZE; } if (copy_to_user(buf, pMyNode->_buffer + *f_pos, count)) { printk(KERN_ALERT "copy_to_user fails\n"); return 0; } *f_pos += count; if(*f_pos >= BUFFER_SIZE) { return 0; } return count; } ssize_t hellocdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { struct Hellocdev_Node_Struct *pMyNode = filp->private_data; if (count >= BUFFER_SIZE) { count = BUFFER_SIZE; } if (copy_from_user(pMyNode->_buffer, buf, count)) { printk(KERN_ALERT "copy_from_user fails\n"); return 0; } return count; } struct file_operations fops = { .owner = THIS_MODULE, .read = hellocdev_read, .write = hellocdev_write, .open = hellocdev_open, .release = hellocdev_release, }; static int __init hello_init(void) { int result = 0; printk(KERN_ALERT "Hello world\n"); if(default_Major != 0) { MyNode._devnum = MKDEV(default_Major, default_Minor); result = register_chrdev_region(MyNode._devnum, default_DevNum, "hellocdev"); }else { result = alloc_chrdev_region(&MyNode._devnum, default_Minor, default_DevNum, "hellocdev"); default_Major = MAJOR(MyNode._devnum); } if(result < 0) { printk(KERN_ALERT "Get CDev Fails:[ %d , %d ]\n", default_Major, default_Minor); return result; } printk(KERN_ALERT "Get CDev Success:[ %d , %d ]\n", default_Major, default_Minor); cdev_init(&MyNode._cdev, &fops); MyNode._cdev.owner = THIS_MODULE; MyNode._cdev.ops = &fops; result = cdev_add(&MyNode._cdev, MyNode._devnum, default_DevNum); if (result) { printk(KERN_ALERT "cdev_add Fails\n"); } return 0; } static void __exit hello_exit(void) { cdev_del(&MyNode._cdev); unregister_chrdev_region(MyNode._devnum, default_DevNum); printk(KERN_ALERT "Goodbye world\n"); } module_init(hello_init); module_exit(hello_exit);
注册设备:
首先插入驱动:
root@ubuntu:/home/cstriker1407/drivers/hellocdev# make make -C /lib/modules/3.13.0-37-generic/build SUBDIRS=/home/cstriker1407/drivers/hellocdev modules make[1]: 正在进入目录 `/usr/src/linux-headers-3.13.0-37-generic' CC [M] /home/cstriker1407/drivers/hellocdev/hellocdev.o Building modules, stage 2. MODPOST 1 modules CC /home/cstriker1407/drivers/hellocdev/hellocdev.mod.o LD [M] /home/cstriker1407/drivers/hellocdev/hellocdev.ko make[1]:正在离开目录 `/usr/src/linux-headers-3.13.0-37-generic' root@ubuntu:/home/cstriker1407/drivers/hellocdev# insmod hellocdev.ko
然后查看设备号:
cstriker1407@ubuntu:~$ cat /proc/devices Character devices: 。。。。。 250 hellocdev 。。。。。
根据设备号新建节点并读写:
root@ubuntu:/dev# mknod hellocdev c 250 0 root@ubuntu:/dev# echo 12345678 > hellocdev root@ubuntu:/dev# cat hellocdev 12345678
日志:
Oct 26 07:36:17 ubuntu kernel: [ 4019.585615] Goodbye world Oct 26 07:36:27 ubuntu kernel: [ 4029.934183] Hello world Oct 26 07:36:27 ubuntu kernel: [ 4029.934200] Get CDev Success:[ 250 , 0 ] Oct 26 07:36:33 ubuntu kernel: [ 4035.157324] perf samples too long (2505 > 2500), lowering kernel.perf_event_max_sample_rate to 50000 Oct 26 07:37:15 ubuntu kernel: [ 4077.019422] hellocdev_open Called pMyNode->_buffer: Oct 26 07:37:15 ubuntu kernel: [ 4077.019469] hellocdev_release Called pMyNode->_buffer:12345678 Oct 26 07:37:15 ubuntu kernel: [ 4077.019469] Oct 26 07:37:18 ubuntu kernel: [ 4079.967624] hellocdev_open Called pMyNode->_buffer:12345678 Oct 26 07:37:18 ubuntu kernel: [ 4079.967624] Oct 26 07:37:18 ubuntu kernel: [ 4079.967893] hellocdev_release Called pMyNode->_buffer:12345678 Oct 26 07:37:18 ubuntu kernel: [ 4079.967893] Oct 26 07:37:45 ubuntu kernel: [ 4107.149606] Goodbye world
发表评论