前言
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"的用法参考