一. 内存设备结构体
static const struct memdev { const char *name; mode_t mode; const struct file_operations *fops; struct backing_dev_info *dev_info; } devlist[] = { [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi }, #ifdef CONFIG_DEVKMEM [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi }, #endif [3] = { "null", 0666, &null_fops, NULL }, #ifdef CONFIG_DEVPORT [4] = { "port", 0, &port_fops, NULL }, #endif [5] = { "zero", 0666, &zero_fops, &zero_bdi }, [7] = { "full", 0666, &full_fops, NULL }, [8] = { "random", 0666, &random_fops, NULL }, [9] = { "urandom", 0666, &urandom_fops, NULL }, [11] = { "kmsg", 0, &kmsg_fops, NULL }, #ifdef CONFIG_CRASH_DUMP [12] = { "oldmem", 0, &oldmem_fops, NULL }, #endif };
二.初始化
1.内存设备初始化
static int __init chr_dev_init(void) { int minor; int err; err = bdi_init(&zero_bdi); if (err) return err; if (register_chrdev(MEM_MAJOR, "mem", &memory_fops)) //注册基于内存的设备,捆绑memory_fops printk("unable to get major %d for memory devs\n", MEM_MAJOR); mem_class = class_create(THIS_MODULE, "mem"); //创建"/sys/class/mem" if (IS_ERR(mem_class)) return PTR_ERR(mem_class); mem_class->devnode = mem_devnode; for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { if (!devlist[minor].name) continue; device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),NULL, devlist[minor].name); } //创建devlist数组中的设备"/sys/class/mem/xxx" return tty_init(); }
2.memory_fops
static const struct file_operations memory_fops = { .open = memory_open, .llseek = noop_llseek, };
3.memory_open
static int memory_open(struct inode *inode, struct file *filp) { int minor; const struct memdev *dev; minor = iminor(inode); //根据节点算出次设备号 if (minor >= ARRAY_SIZE(devlist)) return -ENXIO; dev = &devlist[minor]; //根据次设备号获取内存设备 if (!dev->fops) return -ENXIO; filp->f_op = dev->fops; //替换操作函数集 if (dev->dev_info) filp->f_mapping->backing_dev_info = dev->dev_info; //替换memdev->dev_info /* Is /dev/mem or /dev/kmem ? */ if (dev->dev_info == &directly_mappable_cdev_bdi) filp->f_mode |= FMODE_UNSIGNED_OFFSET; if (dev->fops->open) //若存在open方法 return dev->fops->open(inode, filp); //则调用其open方法 return 0; }
三.null
static const struct file_operations null_fops = { .llseek = null_lseek, .read = read_null, .write = write_null, .splice_write = splice_write_null, };
read_null
static ssize_t read_null(struct file *file, char __user *buf,size_t count, loff_t *ppos) { return 0; }
write_null
static ssize_t write_null(struct file *file, const char __user *buf,size_t count, loff_t *ppos) { return count; }
所以往/dev/null读写数据都是一去不回的,黑洞一般
其他的特殊设备差不多