在Linux Kernel中某些特定含义的函数命令有自己的规律,比如这里将简单的介绍一下函数名前双下划线__和devm_xxx函数的意思。
函数名称前的双下划线__
标记需要加锁:
在内核中,有很多函数,有的是需要调用者自己加锁保护的,有些是不需要加锁保护的。对于这些场景,linux kernel采取了统一的策略:基本函数名字是一样的,只不过需要调用者自己加锁保护的那个函数需要增加__的前缀,例如内核有有下面两个函数:setup_irq()和__setup_irq()。
两个函数在kernel/irq/manage.c中定义:
/**
* setup_irq - setup an interrupt
* @irq: Interrupt line to setup
* @act: irqaction for the interrupt
*
* Used to statically setup interrupts in the early boot process.
*/
int setup_irq(unsigned int irq, struct irqaction *act)
{
int retval;
struct irq_desc *desc = irq_to_desc(irq);
if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))
return -EINVAL;
chip_bus_lock(desc);
retval = __setup_irq(irq, desc, act);
chip_bus_sync_unlock(desc);
return retval;
}
EXPORT_SYMBOL_GPL(setup_irq);
标记更接近底层的调用
一般双下划线也用于标记更接近底层的调用,如kernel/irq/manage.c中的__disable_irq_nosync():
```
/** * disable_irq_nosync - disable an irq without waiting
@irq: Interrupt to disable
Disable the selected interrupt line. Disables and Enables are
nested.
Unlike disable_irq(), this function does not ensure existing
instances of the IRQ handler have completed before returning.
This function may be called from IRQ context.
*/
void disable_irq_nosync(unsignedint irq)
{
__disable_irq_nosync(irq);
}
EXPORT_SYMBOL(disable_irq_nosync);
/**
disable_irq - disable an irq and wait for completion
@irq: Interrupt to disable
Disable the selected interrupt line. Enables and Disables are
nested.
This function waits for any pending IRQ handlers for this interrupt
to complete before returning. If you use this function while
holding a resource the IRQ handler may need you will deadlock.
This function may be called - with care - from IRQ context.
*/
void disable_irq(unsignedint irq)
{
if(!__disable_irq_nosync(irq)) synchronize_irq(irq);
}
EXPORT_SYMBOL(disable_irq);
devm_xxx 函数
下面列举一些常用的资源申请接口,它们由各个framework(如clock、regulator、gpio等等)基于device resource management实现。使用时,直接忽略devm_的前缀,后面剩下的部分,driver工程师都很熟悉。只需记住一点,driver可以只申请,不释放,设备模型会帮忙释放。不过如果为了严谨,在driver remove时,可以主动释放(也有相应的接口,这里没有列出)。
externvoiddevm_kzalloc(struct devicedev,size_t size, gfp_t gfp);
void __iomem devm_ioremap_resource(struct devicedev,struct resource *res);
void __iomem devm_ioremap(struct devicedev, resource_size_t offset,unsignedlong size);
struct clk devm_clk_get(struct devicedev,constchar*id);
int devm_gpio_request(struct device dev,unsigned gpio,constcharlabel);
static inline struct pinctrl * devm_pinctrl_get_select(struct device dev,constcharname)
static inline struct pwm_device devm_pwm_get(struct devicedev,constchar*consumer);
struct regulator devm_regulator_get(struct devicedev,constcharid);
static inline int devm_request_irq(struct devicedev,unsignedint irq, irq_handler_t handler,
unsignedlong irqflags,constchardevname,voiddev_id);
struct reset_control devm_reset_control_get(struct devicedev,constchar*id);
```