#include

#include

#include

#include

#include

#include

#include

#define DEVICE_NAME "chrdev_test"

#define DEVICE_MAJOR 0

#define MINOR_BASE 0

#define MINOR_NUM 1

MODULE_LICENSE("Dual BSD/GPL");

MODULE_AUTHOR("colorfulshark@hotmail.com");

static int major = DEVICE_MAJOR;

static int minor_base = MINOR_BASE;

static int minor_num = MINOR_NUM;

static dev_t devno;

static struct cdev *pcdev;

static struct class *test_class;

static struct device *test_device;

static struct file_operations fops = {

.owner = THIS_MODULE,

};

#if 0

module_param(major, int, S_IRWXU);

module_param(minor_base, int, S_IRWXU);

module_param(minor_num, int, S_IRWXU);

#endif

static void request_devno(void) //申请设备号

{

int ret;

if(major) { //静态申请设备号

printk(KERN_ALERT "alloc device number static\n");

devno = MKDEV(major, minor_base);

ret = register_chrdev_region(devno, minor_num, DEVICE_NAME);

} else { //动态申请设备号

printk(KERN_ALERT "alloc device number dynamic\n");

ret = alloc_chrdev_region(&devno, minor_base, minor_num, DEVICE_NAME);

printk(KERN_ALERT "alloc major : %d\n", MAJOR(devno));

}

if(ret < 0) {

printk(KERN_ALERT "register chrdev region failed\n");

}

}

static void free_devno(void) //释放设备号

{

unregister_chrdev_region(devno, minor_num);

}

static int add_cdev(void) //添加字符设备

{

int error;

pcdev = cdev_alloc();

if(pcdev == NULL) {

goto err_no_mem;

}

cdev_init(pcdev, &fops);

pcdev->owner = THIS_MODULE;

error = cdev_add(pcdev, devno, minor_num);

if(error)

goto err_cdev_add;

printk(KERN_ALERT "success to add cdev\n");

return 0;

err_no_mem:

printk(KERN_ALERT "no enough memory\n");

free_devno();

return -ENOMEM;

err_cdev_add:

printk(KERN_ALERT "fail to add cdev\n");

free_devno();

return error;

}

static void del_cdev(void) //删除字符设备

{

cdev_del(pcdev);

}

static void add_dev_node(void) //创建设备节点,自动创建;如果代码中不创建的话需mknode手动创建

{

test_class = class_create(THIS_MODULE, "test_class");

test_device = device_create(test_class, NULL, devno, NULL, "chrdev_test");

}

static void del_dev_node(void) //删除设备节点

{

device_destroy(test_class, devno);

class_destroy(test_class);

}

static int chrdev_init(void)

{

printk(KERN_ALERT "chrdev init\n");

request_devno();

add_cdev();

add_dev_node();

return 0;

}

static void chrdev_exit(void)

{

del_dev_node();

del_cdev();

free_devno();

printk(KERN_ALERT "chrdev exit\n");

}

module_init(chrdev_init);

module_exit(chrdev_exit);

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐