Linux设备驱动---字符设备驱动接口函数

简介: Linux设备驱动---字符设备驱动接口函数

内核提供了三个函数来注册一组字符设备编号,这三个函数分别是 register_chrdev_region()alloc_chrdev_region()register_chrdev()

 

一、register_chrdev和unregister_chrdev

在Linux2.6内核以前注册字符设备的函数接口是register_chrdev,注销字符设备接口函数是unregister_chrdev.

register_chrdev()---老版本字符设备注册函数

static inline int register_chrdev(unsigned int major, const char *name, const struct file_opertations * fops)

参数

说明

Major

表示设备编号。major=0,则表示采用系统动态分配的主设备号;不为0,则表示静态注册

Name

表示设备名字

Fops

在内核内部与驱动设备挂钩

返回值:

major值为0,正常注册后,返回分配的主设备号。如果分配失败,返回 EBUSY 的负值(-EBUSY)。major值若大于linux/major.h(2.4内核)中声明的最大值(#define MAX_CHRDEV255),则返回EINVAL 的负值(-EINVAL)。

指定major值后,若该设备号已被占用,返回EBUSY的负值(-EBUSY)。若正常注册,则返回0值。

 

unregister_chrdev() --- 老版本字符设备注销函数

功能:注销设备

原型:

1. #include <linux.fs.h>
2. 
3. int unregister_chrdev (unsigned int major, const char *name)

说明:

注销设备驱动程序的内核函数

major主设备号

name设备文件

返回值:

major值若大于linux/major.h(2.4内核)中声明的最大值 (#define MAX_CHRDEV255),返回 EINVAL的负值(-EINVAL)。指定了major的值后,若将要注销的major值并不是注册的设备驱动程序,返回EINVAL的负值(-EINVAL)。正常注销则返回0值。

 

二、register_chrdev_region(静态注册)

新接口注册字符设备驱动需要两步:

step1:注册/分配主次设备号

step2:注册字符驱动设备

1. <linux/fs.h>
2. 
3. int register_chrdev_region(dev_t first, unsigned int count, char *name);

参数说明:

参数

说明

first

要分配的设备编号范围的初始值,这组连续设备号的起始设备号,相当于register_chrdefv()中主设备号

count

连续编号范围,是这组设备号的大小(也就是次设备号个数)

name

编号相关的设备名称,(proc/devices);本组设备的驱动名称

 

三、alloc_chrdev_region(动态注册)

1. <linux/fs.h>
2. 
3. int alloc_chrdev_region(dev_t *dev,unisgned baseminor,unsigned count,const char*name)

参数说明:

参数

说明

dev

系统分配所得的设备号。可以用MAJOR和MINOR将主次设备号打印查看

baseminor

次设备号的基准,从第几个设备号开始分配

count

次设备号的个数

name

驱动的名字

返回值:分配成功,返回设备号的第一个参数;分配错误,返回小于零的参数

 

cdev结构体

cdev是一个结构体,里面的成员来共同帮助我们注册驱动到内核中,表达字符设备的,将这个struct cdev结构体进行填充,主要填充的内容就是

1. struct cdev {
2. 
3. struct kobject kobj;
4. 
5. struct module *owner;//填充时,值要为 THIS_MODULE,表示模块
6. 
7. const struct file_operations *ops;//这个file_operations结构体,注册驱动的关键,要填充成这个结构体变量
8. 
9. struct list_head list;
10. 
11. dev_t dev;//设备号,主设备号+次设备号
12. 
13. unsigned int count;//次设备号个数
14. 
15. };

cdev结构体中ops变量让file_operations结构体变量成为cdev的成员,这个结构体会被cdev_add函数向内核注册cdev结构体。

cdev结构体,可以用很多函数来操作他。

如:

1. cdev_alloc:让内核为这个结构体分配内存的
2. 
3. cdev_init:将struct cdev类型的结构体变量和file_operations结构体进行绑定的
4. 
5. cdev_add:向内核里面添加一个驱动,注册驱动
6. 
7. cdev_del:从内核中注销掉一个驱动。注销驱动

 

设备号

(1)dev_t类型(包括了主设备号和次设备号  不同的内核中定义不一样有的是16位次设备号和16位主设备号构成  有的是20为次设备号12位主设备号 )

(2)MKDEV、MAJOR、MINOR三个宏

MKDEV:  是用来将主设备号和次设备号,转换成一个主次设备号的。(设备号)

MAJOR:   从设备号里面提取出来主设备号的。

MINOR宏:从设备号中提取出来次设备号的。

 

关于设备文件的创建

刚开始写Linux设备驱动程序的时候,很多时候都是利用mknod命令手动创建设备节点,实际上Linux内核为我们提供了一组函数,可以用来在模块加载的时候自动在/dev目录下创建相应设备节点,并在卸载模块时删除该节点,当然前提条件是用户空间移植了udev。

内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类, 内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建好了这个类,再调用 device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。

注意,在2.6较早的内核版本中,device_create(…)函数名称不同,是class_device_create(…),所以在新的内核中编译以前的模块程序有时会报错,就是因为函数名称不同,而且里面的参数设置也有一些变化。

      struct class和device_create(…) 以及device_create(…)都定义在/include/linux/device.h中,使用的时候一定要包含这个头文件,否则编译器会报错。

class_create()

struct class *class_create(struct module *owner, const char *name);

owner    指向拥有这个struct类的模块的指针

name     指向该类名称的字符串指针

 

device_create()

struct device *device_create(struct class *class, struct device *parent, dev_t devt, const char *fmt, ...)

第一个参数指定所要创建的设备所从属的类

第二个参数是这个设备的父设备,如果没有就指定为NULL

第三个参数是设备号

第四个参数是设备名称

第五个参数是从设备号

相关文章
|
7天前
|
Linux 开发工具 Perl
在Linux中,有一个文件,如何删除包含“www“字样的字符?
在Linux中,如果你想删除一个文件中包含特定字样(如“www”)的所有字符或行,你可以使用多种文本处理工具来实现。以下是一些常见的方法:
31 5
|
23天前
|
Linux 开发工具 Perl
Linux命令替换目录下所有文件里有"\n"的字符为""如何操作?
【10月更文挑战第20天】Linux命令替换目录下所有文件里有"\n"的字符为""如何操作?
34 4
|
2月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
94 6
|
2月前
|
Linux Shell
Linux系统编程:掌握popen函数的使用
记得在使用完 `popen`打开的流后,总是使用 `pclose`来正确关闭它,并回收资源。这种做法符合良好的编程习惯,有助于保持程序的健壮性和稳定性。
139 3
|
2月前
|
Linux
在Linux内核中根据函数指针输出函数名称
在Linux内核中根据函数指针输出函数名称
|
3月前
|
Java Linux API
Linux设备驱动开发详解2
Linux设备驱动开发详解
43 6
|
3月前
|
存储 缓存 Unix
Linux 设备驱动程序(三)(上)
Linux 设备驱动程序(三)
38 3
|
3月前
|
Linux PHP
Linux CentOS 宝塔 Suhosin禁用php5.6版本eval函数详细图文教程
【8月更文挑战第27天】本文介绍两种禁用PHP执行的方法:使用`PHP_diseval_extension`禁用和通过`suhosin`禁用。由于`suhosin`不支持PHP8,仅适用于PHP7及以下版本,若服务器安装了PHP5.6,则需对应安装`suhosin-0.9.38`版本。文章提供了详细的安装步骤,并强调了宝塔环境下与普通环境下的PHP路径差异。安装完成后,在`php.ini`中添加`suhosin.so`扩展并设置`executor.disable_eval = on`以禁用执行功能。最后通过测试代码验证是否成功禁用,并重启`php-fpm`服务生效。
43 2
|
3月前
|
Linux
Linux 设备驱动程序(四)
Linux 设备驱动程序(四)
21 1
|
3月前
|
存储 数据采集 缓存
Linux 设备驱动程序(三)(中)
Linux 设备驱动程序(三)
35 1