创建字符设备

转载 2016年05月30日 18:37:47
将创建字符设备的三种方法记录一下,以便以后参考.

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;
}

相关文章推荐

linux之misc及使用misc创建字符设备

1:linux字符设备及udev      1.1字符设备 字符设备就是:一个一个字节来进行访问的,不能对字符设备进行随机读写。简单字符设备创建实例如下: #include #include...

android如何在init.rc中添加/dev/字符设备节点创建权限

android如何在init.rc中添加/dev/字符设备节点创建权限 system/core/init/init.c system/core/init/keywords.h:77...

使用ioctl方法创建字符设备驱动

1  ioctl介绍: 用户空间ioctl :int ioctl(int fd,unsinged long cmd,...) fd-文件描述符 cmd-对设备的发出的控制命令 ...表示这是一...

linux下字符设备驱动的三种创建方式

第一种:作为混杂设备驱动 第二种:使用class_create和device_create 第三种:使用cdev结构体...

创建字符设备的三种方法

将创建字符设备的三种方法记录一下,以便以后参考.1. 使用早期的register_chardev()方法#include#include#include#includeint init_module(...

Linux增加字符设备驱动实验

  • 2017年05月11日 19:08
  • 3KB
  • 下载

Linux创建字符设备 自动生成设备节点

1. 创建字符设备 生成设备节点 2. busybox   Linux System Utilities --->   [*] mdev   [*] Support /etc/...

linu字符设备开发.ppt

  • 2013年10月25日 09:59
  • 5.91MB
  • 下载

字符设备驱动程序的开发

  • 2013年05月08日 21:01
  • 32KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:创建字符设备
举报原因:
原因补充:

(最多只允许输入30个字)