Linux设备开发基础——字符设备(二)

1、字符设备号的分配和释放

分配设备号有如下两种方式,前者为字符设备号已知的情况下使用,而后者通过名称可以知道为动态申请未被占用的字符设备号;这两个函数一般在 cdev_init和 cdev_add 前调用。

int register_chrdev_region(dev_t, unsigned, const char *);
int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *);

相对应的在设备注销阶段需要调用设备号的释放,在cdev_del 后需要调用如下函数:

void unregister_chrdev_region(dev_t from, unsigned count);

 

2、字符设备驱动模板

#include <linux/module.h>
#include <linux/cdev.h>
#include <linux/fs.h>

#define DEVICE_NAME    "xcdeva"
static int xcdev_major = 230;

struct cdev xcdev_dev;

static int xcdev_open(struct inode *inode, struct file *file)
{
    printk("cdev Open Called!\n");
    return 0;
}

static int xcdev_release(struct inode *inode, struct file *file)
{
    printk("cdev Release Called!\n");
    return 0;
}

static ssize_t xcdev_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
    printk("cdev Read Called!\n");
    return 0;
}

static ssize_t xcdev_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
	printk("cdev Write Called!\n");
    return 0;
}

static long xcdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	printk("cdev ioctl Called!\n");
    return 0;
}

static struct file_operations xcdev_fops =
{
    .owner  =   THIS_MODULE,
    .open   =   xcdev_open,
    .release =  xcdev_release,
    .read   =   xcdev_read,
    .write  =   xcdev_write,
    .unlocked_ioctl  =   xcdev_ioctl,
};

static int __init xcdev_init(void)
{
	int ret;
	dev_t xcdev_no = MKDEV(xcdev_major, 0);
    
	printk("xcdev_init\n");
	
	if (xcdev_major) {
		/* 如果主设备号非0, 则为指定的设备号,采用静态注册设备号的方式 */
		register_chrdev_region(xcdev_no, 1, DEVICE_NAME);
	} else {
		/* 动态分配字符设备号 xcdev_no*/
		alloc_chrdev_region(&xcdev_no, 0, 1, DEVICE_NAME);
		xcdev_major = MAJOR(xcdev_no);	//主设备号通过动态分配的xcdev_no获取
	}
	
	/* 初始化xcdev_dev.cdev 字符设备 */
	cdev_init(&xcdev_dev, &xcdev_fops);
	xcdev_dev.owner = THIS_MODULE;

	ret = cdev_add(&xcdev_dev, xcdev_no, 1);
	if(ret) {	
		printk("err: cdev_add failed!\n");
		return -1;
	}
	
    return 0;
}

static void __exit xcdev_exit(void)
{
	unregister_chrdev_region(xcdev_dev.dev, 1);
	cdev_del(&xcdev_dev);
	
	printk("xcdev_exit\n");
}

module_init(xcdev_init);
module_exit(xcdev_exit);

MODULE_AUTHOR("mhp0114");
MODULE_DESCRIPTION("xcdev");
MODULE_LICENSE("GPL");

3、Makefile

KERNELDIR ?= ../../kernel/linux_kernel
PWD := $(shell pwd)
obj-m := xcdev.o
CROSS_COMPILE = arm-linux-

all:
	$(MAKE) -C $(KERNELDIR) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) -Wall modules

clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*

.PHONY: all clean

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页