设备驱动分层:设备节点,设备驱动相关 用了半个月来看字符设备中的错综复杂的结构体,以后要达到的标准是从一个Hello World模板直接写出一个字符设备驱动程序。
设备节点相关:
freg_init()
{
err = alloc_chrdev_region(&dev, 0, 1 , FREG_DEVNODE_NAME);
freg_major = MAJOR(dev);
freg_minor = MINOR(dev);
..........
}
freg_exit()
{
unregister_chrdev_region(MKDEV(freg_major, freg_minor), 0, 1 , FREG_DEVNODE_NAME);
..........
}
字符设备驱动层:static struct file_operations freg_fops = {
.owner = THIS_MODULE,
.open = freg_open,
.release = freg_release,
.read = freg_read,
.write = freg_write,
};
freg_init()
{
cdev_init(&(dev->dev), &freg_fops);
err = cdev_add(&(dev->dev),devno, 1);
..........
}
freg_exit()
{
cdev_del(&(freg_dev->dev));
..........
}
完整代码:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/cdev.h> #include <asm/uaccess.h> static struct cdev *freg_cdev; //An instance of a character device static dev_t ndev; //The node of the device /* "freg"设备的全局变量 */ static int freg_var = 0; //static int freg_major = 250; static int freg_major = 0; static int freg_minor = 0; static ssize_t freg_read(struct file *filp, char __user *buf, size_t sz, loff_t *off) { printk("In the freg_read() function!\n"); /* 将freg_var从内核空间复制到用户空间 */ if (copy_to_user(buf, &freg_var, sizeof(int))) { return - EFAULT; } printk("freg_read enter ,the data is %d\n",freg_var); return sizeof(int); } static ssize_t freg_write(struct file* filp, const char __user *buf, size_t count, loff_t* f_pos) { printk("In the freg_write() function!\n"); /* 将用户空间的数据复制到内核空间的freg_var */ if (copy_from_user(&freg_var, buf, sizeof(int))) { return -EFAULT; } printk("freg_write enter ,the data is %d\n",freg_var); return sizeof(int); } // file_operations is a very important data struct in character type device struct file_operations freg_ops = { .owner = THIS_MODULE, .read = freg_read, .write = freg_write, }; // initialization function of the module static int __init freg_init(void) { int err; printk(KERN_ALERT"Initializing freg device.\n"); // -----------------------设备号相关-------------------------- err = alloc_chrdev_region(&ndev, 0, 1, "freg"); //allocate the device node number dynamically if(err < 0) return err; freg_major = MAJOR(ndev); freg_minor = MINOR(ndev); printk("freg_init():major=%d, minor=%d\n", MAJOR(ndev), MINOR(ndev)); // -------------------------完------------------------------ // ----------------------设备驱动相关-------------------------- freg_cdev = cdev_alloc(); cdev_init(freg_cdev, &freg_ops); //initialize the device instance freg_cdev->owner = THIS_MODULE; //freg_cdev->ops = &freg_ops; //可以不做,因为cdev_init会将freg_ops赋值 err = cdev_add(freg_cdev, ndev, 1);//register the char_dev into the system if(err < 0) return err; // -------------------------完-------------------------------- printk(KERN_ALERT"Succedded to initialize freg device.\n"); return 0; } static void __exit freg_exit(void) { ndev = MKDEV(freg_major, freg_minor); printk(KERN_ALERT"Destroy freg device.\n"); cdev_del(freg_cdev); //unregister the char_dev from the system unregister_chrdev_region(ndev, 1);//free the device node number } MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Fake Register Driver"); module_init(freg_init); module_exit(freg_exit);
编译好后,insmod freg.ko加载驱动。
# cat /proc/devices | grep freg
通过以上命令来查找freg的主设备号
# mknod /dev/freg c 250 0
创建设备节点
应用程序测试:
测试结果: