linux module_xxx_driver宏定义

module_xxx_driver宏定义

在linux驱动中,一般每个模块该函数都需要加载,通常加载步骤是:

static int __init xxx_init(void)
{
	....../* 模块各种初始化内容*/
	return 0;
}

static void __exit xxx_exit(void)
{
	....../* 模块卸载时需要的东西*/
}
module_init(xxx_init);
module_exit(xxx_exit);

i2c注册过程

在i2c驱动中,一般在模块入口函数注册i2c_driver结构体,一般普通操作如下

static struct i2c_driver xxx_driver;	/* 定义i2c设备驱动结构体	*/
static int __init xxx_init(void)
{
	return i2c_add_driver(&xxx_driver);	/* 注册i2c驱动	*/
}
static void __exit xxx_exit(void)
{
	i2c_del_driver(&xxx_driver);	/* 注销i2c驱动	*/
}
module_init(xxx_init);
module_exit(xxx_exit);

但是,linux也定义了一个宏定义module_i2c_driver(struct i2c_driver)来使我们简化编写过程,一行搞定!如下:

struct i2c_driver xxx_driver;
module_i2c_driver(xxx_driver);	/* 只需此步骤就可以将上面一系列代码省去*/

module_i2c_driver()此宏定义执行步骤如下:

/include/linux/i2c.h文件下的第621行左右有此宏定义
#define module_i2c_driver(__i2c_driver) \
	module_driver(__i2c_driver, i2c_add_driver, \
			i2c_del_driver)
			
然后module_driver也是一个宏定义在/include/linux/device.h文件下的1260行左右有此定义
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
	return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
	__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

将上面展开就是:
static int __init __i2c_driver_init(void)
{
	return i2c_add_driver(&__i2c_driver);	/* 注册i2c驱动函数	*/
}
static void __exit __i2c_driver_exit(void)
{
	i2c_del_driver(&__i2c_driver);	/* 注销i2c驱动函数	*/
}
module_init(__i2c_driver_init);
module_exit(__i2c_driver_exit);

由此可见,module_i2c_driver这个宏定义的作用就是帮我们注册驱动,和上面手动注册过程一模一样。

因此,在注册时,我们既可以手动注册驱动,也可以使用module_i2c_driver宏定义来注册驱动。

platform注册过程

在platform驱动中,一般在驱动入口在注册platform驱动,一般过程如下:

static struct platform_driver xxx_driver;
static int __init xxx_init(void)
{
    return platform_driver_register(&xxx_driver);	/* platform驱动注册函数*/
}

static void __exit xxx_exit(void)
{
    platform_driver_unregister(&xxx_driver);	/* platform驱动注销函数	*/
}

module_init(xxx_init);
module_exit(xxx_exit);

如果使用module_platform_driver(struct platform_driver)宏定义,那么驱动注册过程将代码将减少很多,如下:

static platform_driver xxx_driver;
module_platform_driver(xxx_driver);

modlue_platform_driver宏定义执行步骤是:

/include/linux/platform_device文件下第221行有此宏定义
#define module_platform_driver(__platform_driver) \
	module_driver(__platform_driver, platform_driver_register, \
			platform_driver_unregister)
和上面module_i2c_driver的内容一样,就是传入进去的注册函数不一样

然后module_driver也是一个宏定义在/include/linux/device.h文件下的1260行左右有此定义,
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
	return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
	__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

将上面展开就是:
static int __init __platform_driver_init(void)
{
	return platform_driver_register(&__platform_driver);	/* 注册platform驱动函数	*/
}
static void __exit __platform_driver_exit(void)
{
	platform_driver_unregister(&__platform_driver);	/* 注销platform驱动函数	*/
}
module_init(__platform_driver_init);
module_exit(__platform_driver_exit);

有此可见,platform驱动代码既可以写成上面一系列过程也可以写module_platform_driver()宏定义。

SPI 注册过程 (2020/3/22更新)

在SPI驱动中,一般在驱动入口注册驱动函数,如下:

struct spi_driver xxx_driver;
static int __init xxx_init(void)
{
    /* 当注册后次spi的操作函数就可以使用了  */
    return spi_register_driver(&xxx_driver);	/* SPI驱动注册函数	*/
}

static void __exit xxx_exit(void)
{
    spi_unregister_driver(&xxx_driver);	/* SPI驱动注销函数	*/
}
module_init(xxx_init);
module_exit(xxx_exit);

如果使用module_spi_driver(struct spi_driver)宏定义来注册的话,就会省去很多代码,如下:

module_spi_driver(xxx_driver)

module_spi_driver宏定义执行步骤是:

/include/linux/spi.h文件下第214行有此宏定义
#define module_spi_driver(__spi_driver) \
	module_driver(__spi_driver, spi_register_driver, \
			spi_unregister_driver)
和上面module_i2c_driver的内容一样,就是传入进去的注册函数不一样

然后module_driver也是一个宏定义在/include/linux/device.h文件下的1260行左右有此定义,
#define module_driver(__driver, __register, __unregister, ...) \
static int __init __driver##_init(void) \
{ \
	return __register(&(__driver) , ##__VA_ARGS__); \
} \
module_init(__driver##_init); \
static void __exit __driver##_exit(void) \
{ \
	__unregister(&(__driver) , ##__VA_ARGS__); \
} \
module_exit(__driver##_exit);

将上面展开就是:
static int __init __spi_driver_init(void)
{
	return spi_register_driver(&__spi_driver);	/* 注册spi驱动函数	*/
}
static void __exit __spi_driver_exit(void)
{
	spi_unregister_driver(&__spi_driver);	/* 注销spi驱动函数	*/
}
module_init(__spi_driver_init);
module_exit__spi_driver_exit);

有此可见,spi驱动代码既可以写成上面一系列过程也可以写module_spi_driver()宏定义。

好像看来如果都使用宏定义来注册驱动,名字、使用方法差不多,区别就是换了一个不同驱动模型的名字:

i2c_driver->module_i2c_driver
platform_driver->module_platform_driver
spi_driver->module_spi_driver

目前就学了这三个驱动平台,所以总结的也不是很严谨,但是也值得参考,以后学习到更多的linux驱动注册过程,在继续添加。

发布了15 篇原创文章 · 获赞 7 · 访问量 273

猜你喜欢

转载自blog.csdn.net/weixin_42397613/article/details/104908965
今日推荐