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

在 Linux 内核中,字符设备是一种非常常见的设备类型。在许多应用中,我们需要按字节流的方式访问设备,比如串口、并口、输入输出设备等等。在 Linux 中,字符设备的实现方式是通过注册一个字符设备驱动程序,并将其与一段内存区域绑定,将该区域当做一个文件来访问。那么在 Linux 内核中,字符设备是如何注册的呢?本文将对此进行详细讲解。

在 Linux 内核中,注册字符设备的函数是 `register_chrdev`。它定义在 `linux/fs.h` 文件中,其函数原型如下:

```c

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

```

其中,参数 `major` 是该设备的主设备号,参数 `name` 是设备的名称,参数 `fops` 是该设备的操作函数集合,包括了设备读写、打开关闭等操作。

在注册字符设备时,我们一般需要为其分配一个主设备号(minor 设备号可以在设备驱动程序中自行分配),这个主设备号用来标志一类设备,可以让系统识别该设备并将其与相应的设备驱动程序绑定,从而响应用户程序的访问请求。同时,我们还需要指定设备的名称,以便用户程序打开该文件。最后,我们需要指定设备的操作函数集合,这些函数包括:打开设备、关闭设备、读数据、写数据等操作。在这些操作函数中,内核实现了对设备的访问逻辑。

下面是一个简单的字符设备驱动程序示例:

```c

#include

#include

#include

#include

static int chardev_example_open(struct inode *inode, struct file *file)

{

printk("Example chardev opened successfully!\n");

return 0;

}

static ssize_t chardev_example_read(struct file *file, char __user *buf, size_t len, loff_t *offset)

{

printk("Data of example chardev read successfully!\n");

return 0;

}

static ssize_t chardev_example_write(struct file *file, const char __user *buf, size_t len, loff_t *offset)

{

printk("Data of example chardev write successfully!\n");

return len;

}

static int chardev_example_release(struct inode *inode, struct file *file)

{

printk("Example chardev released successfully!\n");

return 0;

}

static const struct file_operations chardev_example_fops = {

.owner = THIS_MODULE,

.read = chardev_example_read,

.write = chardev_example_write,

.open = chardev_example_open,

.release = chardev_example_release,

};

static dev_t devno;

static struct cdev chardev_example_cdev;

static int __init chardev_example_init(void)

{

int ret;

/* 请求设备号 */

ret = alloc_chrdev_region(&devno, 0, 1, "chardev_example");

if (ret < 0) {

printk("Cannot allocate chardev devno!\n");

return ret;

}

/* 初始化字符设备 */

cdev_init(&chardev_example_cdev, &chardev_example_fops);

chardev_example_cdev.owner = THIS_MODULE;

/* 将字符设备注册到系统 */

ret = cdev_add(&chardev_example_cdev, devno, 1);

if (ret < 0) {

printk("Cannot add chardev example device to system!\n");

return ret;

}

printk("Chardev example module initialized successfully!\n");

return 0;

}

static void __exit chardev_example_exit(void)

{

cdev_del(&chardev_example_cdev);

unregister_chrdev_region(devno, 1);

printk("Chardev example module exited successfully!\n");

}

module_init(chardev_example_init);

module_exit(chardev_example_exit);

MODULE_LICENSE("GPL");

```

在上面的示例中,我们首先定义了一些设备操作函数,包括打开、关闭、读取和写入数据。然后,在 `chardev_example_init` 函数中,我们调用了 `alloc_chrdev_region` 函数请求一个设备号,该函数将分配一个可用的设备号并返回。然后,我们调用 `cdev_init` 函数来初始化我们的字符设备,将其绑定到格外定义的操作函数集合 `chardev_example_fops`。最后,我们使用 `cdev_add` 函数将设备添加到系统中。

在 `chardev_example_exit` 函数中,我们调用 `cdev_del` 和 `unregister_chrdev_region` 函数来将设备从系统中删除。

总结:

在 Linux 内核中,注册字符设备需要调用 `register_chrdev` 函数。这个函数有三个参数,分别是设备的主设备号、设备的名称以及设备的操作函数集合。在注册字符设备时,我们需要为其分配一个主设备号,并指定相应的名称和操作函数集合。


点赞(101) 打赏
如果你喜欢我们的文章,欢迎您分享或收藏为众码农的文章! 我们网站的目标是帮助每一个对编程和网站建设以及各类acg,galgame,SLG游戏感兴趣的人,无论他们的水平和经验如何。我们相信,只要有热情和毅力,任何人都可以成为一个优秀的程序员。欢迎你加入我们,开始你的美妙旅程!www.weizhongchou.cn

评论列表 共有 0 条评论

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