linux常用宏解析

前言
linux内核源码里有很多宏,为了能更好地理解内核和驱动源码,有必要对一些常用宏做一个梳理和解析,在此专门做一篇博文来帮助学习,并在以后的学习中逐步添加和完善。

正文

1._IOR(type,nr,size)
用法:

 #define GPIO_IOC_MAGIC					'G'

#define IOCTL_GPIO_GETVALUE				_IOR(GPIO_IOC_MAGIC, 3, int)

宏解析:

#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size)))
->>
#define _IOC(dir,type,nr,size) \
(((dir) << _IOC_DIRSHIFT) | \
((type) << _IOC_TYPESHIFT) |
((nr) << _IOC_NRSHIFT) |
((size) << _IOC_SIZESHIFT))

#ifndef _IOC_READ
#define _IOC_READ 2U
#endif
->>

#define _IOC(dir,type,nr,size) \
(((dir) << 30) | \
((type) << 8) |
((nr) << 0) |
((size) << 16))

由上分析可知_IOC宏把四个参数拼成了一个32位的数字,该数字的组成如下
在这里插入图片描述
所以#define IOCTL_GPIO_GETVALUE _IOR(GPIO_IOC_MAGIC, 3, int)语句设置IOCTL_GPIO_GETVALUE的值为
在这里插入图片描述

2.MKDEV,MAJOR,MINOR
定义:

#define MINORBITS	20
#define MINORMASK	((1U << MINORBITS) - 1)

#define MAJOR(dev)	((unsigned int) ((dev) >> MINORBITS))
#define MINOR(dev)	((unsigned int) ((dev) & MINORMASK))
#define MKDEV(ma,mi)	(((ma) << MINORBITS) | (mi))

所以dev设备号的结构
在这里插入图片描述

3.DEFINE_SPINLOCK
用法:

static DEFINE_SPINLOCK(gpio_lock);

宏解析:

#define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 }


#define __RAW_SPIN_LOCK_INITIALIZER(lockname)	\
	{					\
	.raw_lock = __ARCH_SPIN_LOCK_UNLOCKED,	\
	SPIN_DEBUG_INIT(lockname)		\
	SPIN_DEP_MAP_INIT(lockname) }


#define __SPIN_LOCK_INITIALIZER(lockname) \
	{ { .rlock = __RAW_SPIN_LOCK_INITIALIZER(lockname) } }

#define __SPIN_LOCK_UNLOCKED(lockname) \
	(spinlock_t ) __SPIN_LOCK_INITIALIZER(lockname)

#define DEFINE_SPINLOCK(x)	spinlock_t x = __SPIN_LOCK_UNLOCKED(x)

static DEFINE_SPINLOCK(gpio_lock);->>
spinlock_t gpio_lock=(spinlock_t ){{.rlock = {{0}}}}
该宏定义一个自旋锁,并初始化自旋锁不可用

4.LIST_HEAD(name)
用法:

static LIST_HEAD(omap_hwmod_list);

定义:

struct list_head {
	struct list_head *next, *prev;
};

#define LIST_HEAD_INIT(name) { &(name), &(name) }

#define LIST_HEAD(name) \
	struct list_head name = LIST_HEAD_INIT(name)

所以static LIST_HEAD(omap_hwmod_list);等效于
struct list_head omap_hwmod_list = {&omap_hwmod_list ,&omap_hwmod_list};

5.SYSCALL_DEFINE3

用法:

SYSCALL_DEFINE3(init_module, void __user *, umod,
		unsigned long, len, const char __user *, uargs)

定义:

#define __SC_DECL1(t1, a1)	t1 a1
#define __SC_DECL2(t2, a2, ...) t2 a2, __SC_DECL1(__VA_ARGS__)
#define __SC_DECL3(t3, a3, ...) t3 a3, __SC_DECL2(__VA_ARGS__)
#define __SC_DECL4(t4, a4, ...) t4 a4, __SC_DECL3(__VA_ARGS__)
#define __SC_DECL5(t5, a5, ...) t5 a5, __SC_DECL4(__VA_ARGS__)
#define __SC_DECL6(t6, a6, ...) t6 a6, __SC_DECL5(__VA_ARGS__)

#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)

#define SYSCALL_DEFINEx(x, sname, ...)				\
	__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)


#define __SYSCALL_DEFINEx(x, name, ...)					\
	asmlinkage long sys##name(__SC_DECL##x(__VA_ARGS__))

所以SYSCALL_DEFINE3(init_module, void __user *, umod,
unsigned long, len, const char __user *, uargs);等效于
asmlinkage long sys_init_module(void __user * umod,
unsigned long len, const char __user * uargs))

6.asmlinkage
用法:

asmlinkage long sys_init_module(void __user * umod,
		unsigned long len, const char __user * uargs))

定义:

#ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE
#endif

#ifndef asmlinkage
#define asmlinkage CPP_ASMLINKAGE
#endif

所以asmlinkage long sys_init_module(void __user * umod,
unsigned long len, const char __user * uargs))
等效于
extern “C” long sys_init_module(void __user * umod,
unsigned long len, const char __user * uargs))

long sys_init_module(void __user * umod,
unsigned long len, const char __user * uargs))
使用extern "C"关键字,它的作用是告诉编译器这段代码是以C编译器来编译,它的底层函数签名是就是函数名称,而不是C++那样的函数名+参数,不支持重载的
关于extern "C"的用法参考

C和C++混合编译

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值