Linux字符设备


Linux字符设备就是一个虚拟的文件,当你读写这个文件的时候感觉就像一个真实的文件。为此,需要实现文件的读写方法。

创建misc设备。misc是Linux中的杂项设备,主设备号是10,次设备号会自动分配,这样编程会简单不少。比较重要的地方就是misc_register,他会注册一个misc设备。

static int __init simple_char_init(void)
{
    // register a misc
    int ret = misc_register(&my_misc_device);
    if(ret){
        printk("failed to register misc device\n");
        return ret;
    }
    my_device = my_misc_device.this_device;
    printk("succeeded register char device: %s\n", DEV_NAME);
    
    // alloc a memory space
    buffer = kmalloc(4096, GFP_KERNEL);
    memset(buffer, 0, 4096);
    return 0;
}

销毁的时候需要dereigster

static void __exit simple_char_exit(void)
{
    printk("removing device\n");
    misc_deregister(&my_misc_device);
    kfree(buffer);
}

然后的话需要实现open, release, read和write的函数

static int mydev_open(struct inode *inode, struct file *file)
{
    int major = MAJOR(inode->i_rdev);
    int minor = MINOR(inode->i_rdev);

    printk("%s: major=%d, minor=%d\n", __func__, major, minor);
    return 0;
}

static int mydev_release(struct inode *inode, struct file *file)
{
    return 0;
}

static ssize_t
mydev_read(struct file*file, char __user *buf, size_t lbuf, loff_t *ppos)
{
    int max_free = MAX_DEVICE_BUFFER_SIZE - *ppos;
    int need_read = max_free > lbuf ? lbuf : max_free;

    int ret = copy_to_user(buf, buffer + *ppos, need_read);
    int actual_read = need_read - ret;
    *ppos += actual_read;
    return actual_read;
}

static ssize_t
mydev_write(struct file* file, const char __user *buf, size_t count, loff_t *f_pos)
{
    int max_free = MAX_DEVICE_BUFFER_SIZE - *f_pos;
    int need_write = max_free > count ? count : max_free;

    int ret = copy_from_user(buffer + *f_pos, buf, need_write);

    int actual_write = need_write - ret;
    *f_pos += actual_write;
    
    return actual_write;
}

static const struct file_operations mydev_fops = {
    .owner = THIS_MODULE,
    .open = mydev_open,
    .release = mydev_release,
    .read = mydev_read,
    .write = mydev_write,
    .mmap = mydev_mmap,
};

static struct miscdevice my_misc_device = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEV_NAME,
    .fops = &mydev_fops
};

简单测试可以用echo和cat。也可以编写测试程序来测试。


Author: 蒋璋
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source 蒋璋 !