全部博文(396)
分类: 嵌入式
2016-09-23 11:47:44
Linux内核中的许多规范需要经过反复查找和阅读才能发现其最终的意义和目的。本篇文章搜集并澄清C语言用法中几个含糊不清,容易混淆的地方。
(1) asmlinkage
asmlinkage 告诉编译器要使用局部堆栈来传递参数,而宏FASTCALL通知编译程序使用通用寄存器来传递参数。
以下是来自 include/linux/linkage.h 的代码(2.4.0):
#ifdef __cplusplus
#define CPP_ASMLINKAGE extern "C"
#else
#define CPP_ASMLINKAGE
#endif
#if defined __i386__
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
#elif defined __ia64__
#define asmlinkage CPP_ASMLINKAGE __attribute__((syscall_linkage))
#else
#define asmlinkage CPP_ASMLINKAGE
#endif
(2) UL
UL常被用在数值常数后,标明该常数为"unsigned long"类型,UL(L代表long)负责告诉编译程序将这一数值当作long型数值来处理。因此,使用UL很有必要,它能够保证特定体系结构内的数据 不会溢出其数据类型所规定的范围。涉及很大的数或长的位掩码时,使用UL有助于编写出与体系结构无关的代码。
Linux代码中有这样的例子,如:
include/linux/kernel.h
===============
#define INT_MAX ((int)(~0U>>1))
#define INT_MIN (-INT_MAX - 1)
#define UINT_MAX (~0U)
#define LONG_MAX ((long)(~0UL>>1))
#define LONG_MIN (-LONG_MAX - 1)
#define ULONG_MAX (~0UL)
(3)inline
关键字inline表明要优化函数的可执行代码,这可以通过将函数的代码合并到调用程序的代码中来实现。Linux内核使用的inline函数大多被定义为static 类型。一个"static inline"函数促使编译程序尝试着将其代码插入到所有调用它的程序中。
这一合并能够免除函数调用的任何开销,#define语句也可以排除额外的函数调用。
另外,使用inline会增加二进制映像的大小,而这会降低访问CPU高速缓存的速度,所以不能在所有的函数定义中使用它。
(4)const 和 volatile
const不一定只代表常数,有时它表示"只读"的意思。例如,"const int * x" 中x是一个指向const整数的指针,因此,可以修改指针,但不能修改这个整数;而在"int const * x"中,x却是一个指向整数的const指针,因而这个整数可以改变,但指针x却不能改变。
关键字volatile表明变量无需警告就可以被修改,它通知编译程序每次使用该变量时都要重新加载其值,而不是存储并访问一个副本。中断处理,硬件寄存器,以及并发进程之间共享的变量都是被标记为volatile的典型例子.
include/asm-i386/spinlock.h
===================
typedef struct {
volatile unsigned int lock;
#if SPINLOCK_DEBUG
unsigned magic;
#endif
} spinlock_t;