一. 内存设备结构体
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读写数据都是一去不回的,黑洞一般
其他的特殊设备差不多