linux驱动---字符设备的注册register_chrdev说起

字符设备在Linux设备驱动中占有重要地位,实际上字符设备驱动程序是Linux驱动程序中最常见的一类设备驱动程序。而字符设备驱动程序的注册是其实现的关键,其中一个重要的函数就是register_chrdev()函数。

一、register_chrdev函数介绍

register_chrdev()函数是Linux字符设备驱动程序实现中最重要的函数之一,通过这个函数可以在Linux中注册一个字符设备驱动。此函数的原型定义如下:

```c

int register_chrdev(unsigned int major,const char *name,const struct file_operations *fops)

```

其中,各个参数意义如下:

- major:表示设备号的主设备号,分配设备号的方式有很多种,其中比较常见的方式就是由开发者在内核源码中定义主设备号,使用时解除定义使用。Linux内核将按照分配的主设备号,紧接着在次设备号中分配一个唯一的设备号。这个唯一的设备号将作为register_chrdev()函数的返回值。主设备号的范围是0到255,其中0是留给系统使用的。

- name:表示注册驱动时对设备的名称进行标识,这个等同于向/dev下添加了一个名为“name”的设备节点。这里提醒一下,在系统中不能出现同名设备,否则会导致无法区分设备节点和设备名。

- fops:表示想要连接到这个设备上的操作函数集,是一个指向文件操作函数集结构体的指针,开发者在实现驱动时需要定义自己的操作函数集。

二、register_chrdev函数的实现方法

在大多数驱动程序中,都是在模块初始化函数中注册字符设备驱动程序,也就是通过module_init()函数注册初始化函数,将register_chrdev函数嵌入模块初始化函数中。一个简单的字符设备驱动程序可以看作是以下方式:

```c

#include

#include

#include

MODULE_LICENSE("GPL");

static int major = 0;

static struct file_operations fops = {...};

static int __init init_dr(void)

{

major = register_chrdev(0, "dev_name", &fops);

if(major < 0){

printk("register_chrdev failed!\n");

return -1;

}

printk("major:%d\n",major);

return 0;

}

static void __exit exit_dr(void)

{

unregister_chrdev(major,"dev_name");

printk("unregister_chrdev!\n");

}

module_init(init_dr);

module_exit(exit_dr);

```

如上代码,注册字符设备的函数可以在初始化模块的函数中进行,同时要记得设定对应的操作函数组。最后将驱动模块从内核中删除时,需要调用unregister_chrdev()函数。

三、register_chrdev函数案例

接下来,我们模拟一个最简单的字符设备驱动,并使用register_chrdev函数进行注册。

1、在开发板中新建mychrdev.c文件,代码如下:

```c

#include

#include

#include

int major;//要注册的主设备号

static int my_open(struct inode *inode, struct file *filp)

{

printk("This is open\n");

return 0;

}

static int my_release(struct inode *inode, struct file *filp)

{

printk("This is release\n");

return 0;

}

static ssize_t my_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)

{

printk("This is read\n");

return 0;

}

static ssize_t my_write(struct file *file, const char __user *buf, size_t size, loff_t *ppos)

{

printk("This is write\n");

return size;

}

struct file_operations fops = {

.owner = THIS_MODULE,

.open = my_open,

.release = my_release,

.read = my_read,

.write = my_write,

};

static int __init my_init(void)

{

int ret;

printk(KERN_INFO "mychrdev init\n");

//1、动态分配主设备号

ret = alloc_chrdev_region(&major, 0, 1, "mychrdev");

if(ret < 0){

printk(KERN_INFO "alloc_chrdev_region error\n");

return ret;

}

printk(KERN_INFO "major:%d\n",major);

//2、注册字符设备驱动

ret = register_chrdev(major, "mychrdev", &fops);

if(ret < 0){

printk(KERN_INFO "register_chrdev error\n");

return ret;

}

printk(KERN_INFO "mychrdev register success!\n");

return 0;

}

static void __exit my_exit(void)

{

//1、取消字符设备

unregister_chrdev(major, "mychrdev");

//2、释放主设备

unregister_chrdev_region(major, 1);

printk(KERN_INFO "mychrdev removed!\n");

}

module_init(my_init);

module_exit(my_exit);

MODULE_AUTHOR("farsight");

MODULE_DESCRIPTION("A Simple Chrdev Driver Module");

MODULE_LICENSE("GPL");

```

其中,我们做了以下几个操作:

- 动态分配主设备号

- 注册字符设备驱动

- 释放主设备号

2、makefile文件编写如下:

```makefile

obj-m:=mychrdev.o

KDIR:=/home/farsight/raspberry/linux-rpi-4.19.y

ccflags-y := -Werror

all:

make -C $(KDIR) M=$(PWD) modules

rm -rf *.o *.mod.c *.order *.symvers *.bak

clean:

make -C $(KDIR) M=$(PWD) clean

```

其中,KDIR表示内核源码所在的位置,必须在该内核源码中进行模块编译。

3、编译运行。在终端中输入以下指令:

```sh

make

sudo insmod mychrdev.ko

```

此时我们已经注册了一个字符设备“mychrdev”,主设备号为254。接下来查看dmesg的输出结果,可以得到如下结果:

```sh

farsight@raspberrypi:~/module$ sudo insmod mychrdev.ko

farsight@raspberrypi:~/module$ dmesg

[91737.699489] mychrdev init

[91737.699674] major:254

[91737.700840] mychrdev register success!

```

表示注册成功。我们还可以在/dev下查看到相应创建的设备节点/dev/mychrdev。

可以在驱动中加入open、read、write以及release等基本操作函数,实现对字符设备的简单读写操作。例如,我们在终端中输入以下指令:

```sh

echo 'hello world'>/dev/mychrdev

```

可以在终端中查看到my_write函数的输出,“This is write”。

四、register_chrdev函数总结

register_chrdev函数是Linux驱动程序中最常用的函数之一,其作用是将字符设备注册到内核中,从而使应用程序可以通过/dev设备节点来访问字符设备驱动的功能接口。

本篇文章介绍了register_chrdev函数的实现方法、案例分析及其参数的意义,希望可以对大家掌握register_chrdev函数的技巧和实现原理提供一些帮助。

壹涵网络我们是一家专注于网站建设、企业营销、网站关键词排名、AI内容生成、新媒体营销和短视频营销等业务的公司。我们拥有一支优秀的团队,专门致力于为客户提供优质的服务。

我们致力于为客户提供一站式的互联网营销服务,帮助客户在激烈的市场竞争中获得更大的优势和发展机会!

点赞(89) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部