• 创建字符设备的三种方法


    将创建字符设备的三种方法记录一下,以便以后参考.
    1. 使用早期的register_chardev()方法
    #include<linux/kernel.h>
    #include
    <linux/module.h>
    #include
    <linux/fs.h>
    #include
    <asm/uaccess.h>
    int init_module(void);
    void cleanup_module(void);
    static int device_open(struct inode*, struct file*);
    static int device_release(struct inode*, struct file*);
    static ssize_t device_read(struct file*, char *, size_t, loff_t*);
    static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
    #define SUCCESS 0
    #define DEVICE_NAME "chardev"
    #define BUF_LEN 80
    static int major;
    static int Device_open = 0;
    static char msg[BUF_LEN];
    static char *msg_ptr;
    static struct file_operations fops =
    {
    .read
    = device_read,
    .write
    = device_write,
    .open
    = device_open,
    .release
    = device_release,
    };
    int init_module(void)
    {
    major
    = register_chrdev(0, DEVICE_NAME, &fops);
    if (major < 0)
    {
    printk(KERN_ALERT
    "Registering char device failed with %d\n", major);
    return major;
    }
    printk(KERN_INFO
    "I was assigned major number %d.\n", major);
    return SUCCESS;
    }
    void cleanup_module(void)
    {
    int ret = unregister_chrdev(major, DEVICE_NAME);
    if (ret < 0)
    {
    printk(KERN_ALERT
    "Error in unregister chrdev %d\n", major);
    }
    }
    static int device_open(struct inode* inode, struct file* file)
    {
    static int counter = 0;
    if (Device_open)
    {
    return -EBUSY;
    }
    Device_open
    ++;
    sprintf(msg,
    "I already told you %d times hello world\nDevice_open=%d\n" ,
    counter++, Device_open);
    msg_ptr
    = msg;
    try_module_get(THIS_MODULE);
    return SUCCESS;
    }
    static int device_release(struct inode* inode, struct file* file)
    {
    Device_open
    --;
    module_put(THIS_MODULE);
    return 0;
    }
    static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
    {
    int bytes_read = 0;
    if (*msg_ptr == '\0')
    return 0;
    printk(KERN_ALERT
    "length=%d\n", length);
    while (length && *msg_ptr)
    {
    put_user(
    *(msg_ptr++), buffer++);
    length
    --;
    bytes_read
    ++;
    }
    return bytes_read;
    }
    static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
    {
    printk(KERN_ALERT
    "Sorry, this operation isn't supported\n");
    return -EINVAL;
    }

    2. 使用cdev的方法
    #include<linux/kernel.h>
    #include
    <linux/module.h>
    #include
    <linux/fs.h>
    #include
    <linux/types.h>
    #include
    <linux/fs.h>
    #include
    <linux/cdev.h>
    #include
    <asm/uaccess.h>
    int init_module(void);
    void cleanup_module(void);
    static int device_open(struct inode*, struct file*);
    static int device_release(struct inode*, struct file*);
    static ssize_t device_read(struct file*, char *, size_t, loff_t*);
    static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
    #define SUCCESS 0
    #define DEVICE_NAME "chardev"
    #define BUF_LEN 80

    static int major;
    static int Device_open = 0;
    static char msg[BUF_LEN];
    static char *msg_ptr;
    static struct cdev *my_cdev;
    static struct file_operations fops =
    {
    .read
    = device_read,
    .write
    = device_write,
    .open
    = device_open,
    .release
    = device_release,
    };
    int init_module(void)
    {
    int err;
    dev_t devid ;
    alloc_chrdev_region(
    &devid, 0, 1, "chardev");
    major
    = MAJOR(devid);
    my_cdev
    = cdev_alloc();
    cdev_init(my_cdev,
    &fops);
    err
    = cdev_add(my_cdev, devid, 1);
    if (err)
    {
    printk(KERN_INFO
    "I was assigned major number %d.\n", major);
    return -1;
    }
    printk(
    "major number is %d\n", MAJOR(devid));
    return SUCCESS;
    }
    void cleanup_module(void)
    {
    cdev_del(my_cdev);
    printk(
    "cleanup done\n");
    }
    static int device_open(struct inode* inode, struct file* file)
    {
    static int counter = 0;
    if (Device_open)
    {
    return -EBUSY;
    }
    Device_open
    ++;
    sprintf(msg,
    "I already told you %d times hello world\nDevice_open=%d\n",
    counter++, Device_open);
    msg_ptr
    = msg;
    try_module_get(THIS_MODULE);
    return SUCCESS;
    }
    static int device_release(struct inode* inode, struct file* file)
    {
    Device_open
    --;
    module_put(THIS_MODULE);
    return 0;
    }
    static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
    {
    int bytes_read = 0;
    if (*msg_ptr == '\0')
    return 0;
    printk(KERN_ALERT
    "length=%d\n", length);
    while (length && *msg_ptr)
    {
    put_user(
    *(msg_ptr++), buffer++);
    length
    --;
    bytes_read
    ++;
    }
    return bytes_read;
    }
    static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
    {
    printk(KERN_ALERT
    "Sorry, this operation isn't supported\n");
    return -EINVAL;
    }
    3. 使用udev在/dev/下动态生成设备文件的方式
    #include<linux/kernel.h>
    #include
    <linux/module.h>
    #include
    <linux/types.h>
    #include
    <linux/fs.h>
    #include
    <linux/cdev.h>
    #include
    <linux/pci.h>
    #include
    <linux/moduleparam.h>
    #include
    <linux/init.h>
    #include
    <linux/string.h>
    #include
    <asm/uaccess.h>
    #include
    <asm/unistd.h>
    #include
    <asm/uaccess.h>
    MODULE_LICENSE(
    "GPL"); /*此处如果不加的话加载的时候会出错*/
    int init_module(void);
    void cleanup_module(void);
    static int device_open(struct inode*, struct file*);
    static int device_release(struct inode*, struct file*);
    static ssize_t device_read(struct file*, char *, size_t, loff_t*);
    static ssize_t device_write(struct file*, const char*, size_t, loff_t*);
    #define SUCCESS 0
    #define DEVICE_NAME "chardev"
    #define BUF_LEN 80

    static int major;
    static int Device_open = 0;
    static char msg[BUF_LEN];
    static char *msg_ptr;
    static struct cdev *my_cdev;
    static struct class *my_class;
    dev_t devid ;
    static struct file_operations fops =
    {
    .read
    = device_read,
    .write
    = device_write,
    .open
    = device_open,
    .release
    = device_release,
    };
    int init_module(void)
    {
    int err;
    alloc_chrdev_region(
    &devid, 0, 1, "chardev");
    major
    = MAJOR(devid);
    my_cdev
    = cdev_alloc();
    cdev_init(my_cdev,
    &fops);
    my_cdev
    ->owner = THIS_MODULE;
    err
    = cdev_add(my_cdev, devid, 1);
    if (err)
    {
    printk(KERN_INFO
    "I was assigned major number %d.\n", major);
    return -1;
    }
    my_class
    = class_create(THIS_MODULE, "chardev_class1");
    if (IS_ERR(my_class))
    {
    printk(KERN_INFO
    "create class error\n");
    return -1;
    }
    class_device_create(my_class, NULL, devid, NULL,
    "chardev" "%d", MINOR(devid));
    printk(
    "major number is %d\n", MAJOR(devid));
    return SUCCESS;
    }
    void cleanup_module(void)
    {
    cdev_del(my_cdev);
    class_device_destroy(my_class, devid);
    class_destroy(my_class);
    printk(
    "cleanup done\n");
    }
    static int device_open(struct inode* inode, struct file* file)
    {
    static int counter = 0;
    if (Device_open)
    {
    return -EBUSY;
    }
    Device_open
    ++;
    sprintf(msg,
    "I already told you %d times hello world\nDevice_open=%d\n",
    counter++, Device_open);
    msg_ptr
    = msg;
    try_module_get(THIS_MODULE);
    return SUCCESS;
    }
    static int device_release(struct inode* inode, struct file* file)
    {
    Device_open
    --;
    module_put(THIS_MODULE);
    return 0;
    }
    static ssize_t device_read(struct file* filp, char *buffer, size_t length, loff_t *offset)
    {
    int bytes_read = 0;
    if (*msg_ptr == '\0')
    return 0;
    printk(KERN_ALERT
    "length=%d\n", length);
    while (length && *msg_ptr)
    {
    put_user(
    *(msg_ptr++), buffer++);
    length
    --;
    bytes_read
    ++;
    }
    return bytes_read;
    }
    static ssize_t device_write(struct file* filp, const char *buff, size_t len, loff_t *off)
    {
    printk(KERN_ALERT
    "Sorry, this operation isn't supported\n");
    return -EINVAL;
    }
  • 相关阅读:
    构建之法(一)
    大二下周总结十四
    寒假学习报告03
    寒假学习报告02
    2019春季学期个人总结
    2019春学习进度报告(第十六周)
    计算英语最长单词连
    2019春学习进度报告(第十五周)
    用户体验评价
    2019春学习进度报告(第十四周)
  • 原文地址:https://www.cnblogs.com/hoys/p/2019233.html
Copyright © 2020-2023  润新知