1、字符设备两种驱动框架
2、实现file_operation后,如何告诉内核?
实际上就是把file_ops注册到内核:major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核
例如内核实际上有一个很大的数组,把fops放到空的数组中的某一个项中,然后返回下标(主设备号)。
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */return 0;
3、写一个hello程序
#include <linux/module.h> #include <linux/fs.h> #include <linux/errno.h> #include <linux/miscdevice.h> #include <linux/kernel.h> #include <linux/major.h> #include <linux/mutex.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/stat.h> #include <linux/init.h> #include <linux/device.h> #include <linux/tty.h> #include <linux/kmod.h> #include <linux/gfp.h> //1、确定主设备号 static int major; static char kernel_buff[1024]; struct class hello_class; #define MIN(a,b) (a<b?a:b) //3、实现fops int hello_drv_open (struct inode *node, struct file *filep) { printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__); } int hello_drv_release (struct inode *node, struct file *filep) { printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__); } ssize_t hello_drv_write (struct file *file, char __user *buff, size_t size, loff_t * offet) { printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__); copy_from_user(kernel_buff, buff, MIN(size,1024)); return MIN(size,1024); } ssize_t hello_drv_read (struct file *file, const char __user * buf, size_t size, loff_t * offset) { printf("%s %s line %d\n",__FILE__,__FUNCTION__,__LINE__); copy_to_user(buff,, kernel_buff, MIN(1024,size)); return MIN(size,1024); } //2、定义自己的fops static struct file_operations hello_drv ={ .owner = THIS_MODULE, .open = hello_drv_open, .read = hello_drv_read, .write = hello_drv_write, .release = hello_drv_release, } static int __init hello_init(void) { major=register_chrdev(0,"hello", &hello_drv); class_create(THIS_MODULE,"hello_class"); device_create(hello_class,NULL,MKDEV(major,0),NULL,"hello");//dev/hello return 0; } static void __exit hello_exit(void) { unregister_chrdev(major, "hello"); class_destroy(hello_class); unregister_chrdev(major,"hello"); } MODULE_LICENSE("GPL");
用户态:
int main(int argc, char **argv) { int fd; char buf[1024]; int len; if(argc <2) { printf("usage:%s -w <string>\n",argv[0]); printf(" %s -r\n",argv[0]) return -1; } fd=open("/dev/hello",O_RDWR); if(fd == -1) { printf("can not open file\n"); return -1; } if((0==strcmp(argv[1],"-w")) && (argc == 3)) { len=strlen(argv[2])+1; len = len < 1024 ? len:1024; write(fd, argv[2],len); } else { len = read(fd, buf, 1024); buf[1023]='\0'; printf("APP read: %s\n", buf); } close(fd); }
KERN_DIR = /home/... all: make -C $(KERN_DIR) M=`pwd` modules clean: make -C $(KERN_DIR) M=`pwd` clean