1. mycdev.c
#include <linux/init.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/fs.h> #define MAJOR_NUM 250 struct mycdev { struct cdev cdev; }; int mycdev_open(struct inode *inode, struct file *file) { printk("Call mycdev_open()\n"); ; } struct file_operations fops = { .owner = THIS_MODULE, .open = mycdev_open, }; struct mycdev mycdev; int mycdev_init(void) { ; dev_t dev; dev = MKDEV(MAJOR_NUM, ); ret = register_chrdev_region(dev, , "mycdev"); ) { printk("register_chrdev_region() error\n"); goto err_register_chrdev_region; } cdev_init(&(mycdev.cdev), &fops); ret = cdev_add(&(mycdev.cdev), dev, ); ) { printk("cdev_add() error\n"); goto err_cdev_add; } printk("mycdev_init()\n"); ; err_cdev_add: unregister_chrdev_region(dev, ); err_register_chrdev_region: return ret; } void mycdev_exit(void) { dev_t dev = mycdev.cdev.dev; cdev_del(&(mycdev.cdev)); unregister_chrdev_region(dev, ); printk("mycdev_exit()\n"); return; } module_init(mycdev_init); module_exit(mycdev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("GNB");
2. Makefile
KERNEL_DIR = /lib/modules/$(shell uname -r)/build PWD = $(shell pwd) ifneq ($(KERNELRELEASE),) obj-m := mycdev.o else .PHONY:default clean default: $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules clean: $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean endif
3. 应用层app
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> int main(int argc, const char *argv[]) { int fd; fd = open("/dev/mycdev",O_RDONLY); printf("fd = %d\n",fd); ); ; }
4. 加载驱动
sudo insmod mycdev.ko
5. 创建设备节点,并指定权限
sudo mknod /dev/mycdev c 250 0
sudo chmod 666 /dev/mycdev
6. 测试字符设备
cat /dev/mycdev
echo "hello world" > /dev/mycdev