Linux驱动——函数浅析(一)

我在人间凑数的一天下午——Linux字符设备驱动函数(一)

字符设备是 Linux 驱动中最基本的一类设备驱动,字符设备就是一个一个字节,按照字节流进行读写操作的设备,读写数据是分先后顺序的。比如我们最常见的点灯、按键、IIC、SPI,LCD 等等都是字符设备,这些设备的驱动就叫做字符设备驱动。

Linux 应用程序如何调用驱动的

在这里插入图片描述

module_init 函数的实现

当bootloader加载完kernel并解压并放置与内存中准备开始运行,首先被调用的函数是start_kernel
内核的加载的时候,会搜索".initcall"中的所有条目,并按优先级加载它们,普通驱动程序的优先级是6
tart_kernel()–>rest_init()–>kernel_init()–>do_basic_setup()–>do_initcalls()
我们使用该函数时:
module_init(fn)—> __initcall(fn) —> device_initcall(fn) —> __define_initcall(fn, 6)

register_chrdev 函数

核心:
注册一个file_operations结构体
得到返回值:主设备号

函数原型:
register_chrdev(unsigned int major, const char *name,
const struct file_operations *fops)
第一个参数:主设备号,一般使用0,让系统分配分配。
第二个参数:设备名称
第三个参数:一个file_operations结构体

查看Linux源码分析函数:
register_chrdev 由 __register_chrdev实现
__register_chrdev中有这么一行代码:
cd = __register_chrdev_region(major, baseminor, count, name);
进入到 __register_chrdev_region 中
__register_chrdev_region函数:
cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL);
返回一个没有分配的char_device_struct 结构体。

设置相关信息
cd->major = major;
cd->baseminor = baseminor;
cd->minorct = minorct;
strlcpy(cd->name, name, sizeof(cd->name));
i = major_to_index(major);
( i= return major % CHRDEV_MAJOR_HASH_SIZE;)

cdev = cdev_alloc();
cdev->owner = fops->owner; cdev->ops = fops; kobject_set_name(&cdev->kobj, “%s”, name); err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);

class_creat和device_create

Linux源码中是这样解释的
class_create
create a struct class structure
This is used to create a struct class pointer that can then be used

  • in calls to device_create().
  • Returns &struct class pointer on success, or ERR_PTR() on error.

函数使用:
hello_class = class_create(THIS_MODULE, “hello_class”);
第一个参数:指定类的所有者是哪个模块。
第二个参数:类名。

device_create
creates a device and registers it with sysfs

  • This function can be used by char device classes. A struct device
  • will be created in sysfs, registered to the specified class.

函数使用:
evice_create(hello_class, NULL, MKDEV(major, 0), NULL, “hello”);
第一个参数:指定所要创建的设备所从属的类。
第二个参数:设备的父设备,如果没有就指定为NULL
第三个参数:设备号(主、次)。
第四个参数:设备中以进行回调的数据。这里为NULL。
第五个参数:设备名称的字符串

总结:
1、内核提供了class_create函数,用它来创建一个类,这个类存放于sysfs下面。
2、调用device_create(…)函数来在/dev目录下创建相应的设备节点。
3、加载模块的时候,用户空间中的udev会自动响应device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。

file_operations结构体:

结构的定义详细看Linux源码
它的每一个成员函数一般都对应一个系统调用
实现open read write 等函数的
static struct file_operations my_drv = {
.owner = THIS_MODULE,
.open = my_drv_open,
.read = my_drv_read,
.write = my_drv_write,
}
my_drv_open(), my_drv_read(), my_drv_write(),三个函数的参数,要符合file_operations结构体中的定义,如何实现函数的功能。

MODULE_LICENSE(“GPL”);
声明遵从GPL许可证,否则编译时,内核会报错。
“GPL” 是指明了 这是GNU General Public License的任意版本

2020/6/11日 17:30

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值