linux设备驱动开发常用API(含部分宏)

static int __init dht11_init(void)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
	return 0;
}
static void __exit dht11_exit(void)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
}

module_init(dht11_init);
module_exit(dht11_exit);

__init

告知编译器,将变量或函数放在一个特殊的区域,标记为初始化的函数,表明该函数供在初始化期间使用。对非模块无效,在模块装载之后,模块装载就会将初始化函数扔掉。这样可以将该函数占用的内存释放出来。

__exit 宏

告知编译器,将变量或函数放在一个特殊的区域,标记为模块的退出函数,对非模块无效,如果一个模块被编译到了内核映像中而不是以模块的形式编译的则该部分内存可以被链接器忽略,即不把它连接到内核中或者可以在系统启动后将它占用的内存给释放掉;同时如果内核不支持模块卸载,则也可以在链接时或者启动后释放该部分区域所占的内存.

static int __init xxx_init(void)

static int __init xxx_init(void)
{

* 返回值:成功:0                   

                失败:负数,绝对值是错误码 * 应用层得到的返回值是-1,错误码保存到errno(每个进程有一个);      标准化errno.h已经明确定义linux/errno.h
}

register_chrdev()

  • 作用:                                                                                                                              注册一个字符设备(可用unregister_chrdev来释放)

  • 缺点:

    每注册个字符设备,还会连续注册0~255个次设备号,使它们绑定在同一个file_operations操作方法结构体上,在大多数情况下,都只用极少的次设备号,所以会浪费很多资源.

  • 函数原型如下:

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

  • 头文件:#include <linux/fs.h>

    函数参数和返回值含义如下:

    major:代表动态申请字符设备的主设备号,对于此设备号函数自动赋值为0

    name:申请设备的设备名 

  • fops:申请设备的操作函数

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

示例代码:

static int major = 0;

static const struct file_operations dht11_fops = {
	.owner = THIS_MODULE,
	.read  = dht11_read,
};

major = register_chrdev(0,"xu_dht11_major",&dht11_fops);

unregister_chrdev()

  • 作用:                                                                                                                              将一个字符设备从Linux内核系统中删除

  • 函数原型如下:

    void unregister_chrdev(unsigned int major, const char *name)

  • 头文件:#include <linux/fs.h>

    函数参数和返回值含义如下:

    major:即将被删除的字符设备区及字符设备的主设备号,函数将根据此参数查找内核中的字符设备。

    name:申请设备的设备名 

  • 返回值:返回void类型的结果,即不返回任何类型的值

示例代码:

static int major;

unregister_chrdev(major,"xu_dht11_major");

class_create()

  • 作用:                                                                                                                               创建一个类 

  • 函数原型如下:

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

  • 头文件:#include <linux/miscdevice.h>  /  #include <linux/device.h>

    函数参数和返回值含义如下:

    * @owner:指向“拥有”这个struct类的模块的指针(一般为THIS_MODULE)

    * @name:指向该类名称的字符串的指针。

  • 返回值:指向得到的class的(struct class *)指针

代码示例:

static struct class *dht11_class;

dht11_class = class_create(THIS_MODULE, "xu_dht11_class");

class_destroy()

  • 作用:                                                                                                                               销毁一个类 
  • 函数原型如下:

    void class_destroy(struct class *cls);

  • 头文件:#include <linux/miscdevice.h>  /  #include <linux/device.h>

    函数参数和返回值含义如下:

    * @cls:struct class结构体类型的变量,代表设备的逻辑类

  • 返回值:返回void类型的结果,即不返回任何类型的值

示例代码:

static struct class *dht11_class;

class_destroy(dht11_class);

platform_driver_register()

  • 作用:                                                                                                                              向内核注册一个平台驱动。 如此时有匹配的平台设备则会引发内核执行平台驱动结构中的 probe 函数
  • 函数原型如下:

    int platform_driver_register(struct platform_driver *drv)

  • 头文件:#include <linux/platform_device.h>

    函数参数和返回值含义如下:

    * drv:要注册的平台驱动结构指针

  • 返回值: 0:注册成功;负数:注册失败

代码示例:

static const struct of_device_id dht11_match[] = {
	{ .compatible = "xu,dht11" },
	{ },
};

static struct platform_driver dht11_driver = {
	.probe      = dht11_probe,
	.remove     = dht11_remove,
	.driver = {
			.name = "xu_dht11",
			.of_match_table = dht11_match,
		},
};


int err;
err = platform_driver_register(&dht11_driver);

platform_driver_unregister()

  • 作用:                                                                                                                              从内核中注销一个平台设备驱动,如此时已匹配平台设备,则会引发内核执行平台驱动结构中的remove 函数
  • 函数原型如下:

    void platform_driver_ unregister (struct platform_driver *drv)

  • 头文件:#include <linux/platform_device.h>

    函数参数和返回值含义如下:

    * drv:要注销的平台驱动结构指针

  • 返回值:返回void类型的结果,即不返回任何类型的值

代码示例:

static const struct of_device_id dht11_match[] = {
	{ .compatible = "xu,dht11" },
	{ },
};

static struct platform_driver dht11_driver = {
	.probe      = dht11_probe,
	.remove     = dht11_remove,
	.driver = {
			.name = "xu_dht11",
			.of_match_table = dht11_match,
		},
};

platform_driver_unregister(&dht11_driver);

device_create()

  • 作用:                                                                                                                              从创建一个设备节点
  • 函数原型如下:struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...);

  • 头文件:#include <linux/device.h>

    函数参数和返回值含义如下:

  • cls:即将创建的逻辑设备相关的逻辑类

    parent:即将创建的逻辑设备的父设备的指针,子设备与父设备的关系是:当父设备不可用时,子设备不可用,子设备依赖父设备,父设备不依赖子设备

  • devt:逻辑设备的设备号

  • drvdata:void类型的指针,代表回调函数的输入参数

  • fmt:逻辑设备的设备名,即在目录/sys/devices/virtual创建的逻辑设备目录的目录名。

  • 返回值:返回值是struct device结构体类型的指针,指向新创建的逻辑设备

代码示例:

static struct class * dht11_class;

dht11_class = class_create(THIS_MODULE, "xu_dht11_class");

device_create(dht11_class, NULL, MKDEV(major, 0), NULL, "xu_dht11_device");

device_destroy()

  • 作用:                                                                                                                              销毁一个设备节点
  • 函数原型如下:void device_destroy(struct class *cls, dev_t devt);

  • 头文件:#include <linux/device.h>

    函数参数和返回值含义如下:

  • cls:struct class类型的变量,代表与待注销的逻辑设备相关的逻辑类,用于Linux内核系统逻辑设备的查找

  • devt:逻辑设备的设备号

  • 返回值:返回void类型的结果,即不返回任何类型的值

代码示例:

static int major;
static struct class *dht11_class;

device_destroy(dht11_class, MKDEV(major, 0));

probe()

  • 作用:     
  • 当平台device和平台driver匹配时,就会调用probe()函数,在此函数一般完成资源的获取以及定时器,中断,内核线程初始化创建设备节点等                                                                                                                 
  • 函数原型如下:int probe(struct platform_device *pdev)

  • 头文件:#include <linux/platform_device.h>

    函数参数和返回值含义如下:

  • pdev : pci里是struct pci_dev *pdev ,这个是由linux内核启动时遍历pci总线后得到的pci设备的描述符

  • 返回值:返回int类型的结果,若是返回0表示成功,

代码示例:

static int dht11_probe(struct platform_device *pdev)
{
	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
/* 1. 获得硬件信息 */
	dht11_desc = gpiod_get(&pdev->dev, "dht11", GPIOD_OUT_HIGH);	
	if (IS_ERR(dht11_desc))
	{	printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
//		return -1;
	}
/* 2. device_create */
	device_create(dht11_class, NULL, MKDEV(major, 0), NULL, "xu_dht11_device");
	return 0;
}


版权声明:本文为weixin_49460450原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。