static inline Linux内联函数

转载 2012年03月24日 16:35:02

asmlinkage/FASTCALL()/fastcall

这三个宏指定了函数参数的传递方式。asmlinkage修饰的函数,其参数通过堆栈传递。FASTCALL()/fastcall,此二者实际上是一样的作用。在Intel i386架构中,它们所修饰的函数,其前三个参数分别通过通用寄存器EAX,ECX和EDX来传递。
它们定义于include/asm-i386/linkage.h:
#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
#define FASTCALL(x) x __attribute__((regparm(3)))
#define fastcall __attribute__((regparm(3)))
此处利用的是函数属性regparm。

static inline内联函数

内联函数有些类似于宏。内联函数的代码会被直接嵌入在它被调用的地方2,调用几次就嵌入几次,没有使用call指令。这样省去了函数调用时的一些额外开销,比如保存和恢复函数返回地址等,可以加快速度。不过调用次数多的话,会使可执行文件变大,这样会降低速度。相比起宏来说,内核开发者一般更喜欢使用内联函数。因为内联函数没有长度限制,格式限制。编译器还可以检查函数调用方式,以防止其被误用。
static inline的内联函数,一般情况下不会产生函数本身的代码,而是全部被嵌入在被调用的地方。如果不加static,则表示该函数有可能会被其他编译单元所调用,所以一定会产生函数本身的代码。所以加了static,一般可令可执行文件变小。内核里一般见不到只用inline的情况,而都是使用static inline。
有时候也可以见到static __inline__。gcc编译参数“-ansi”或者“-std=c89”等会禁用一些关键字,比如“asm”,“inline”等。为了在这种情况下使用内联函数,gcc提供了“__inline__”关键字。不过内核使用的标准是gnu89,所以“inline”和“__inline__”在内核中都可以使用。现在“inline”已经成了C99标准的关键字。gcc未来的缺省标准也将变成基于C99的gnu99。所以现在写内核代码时,推荐使用“inline”关键字,而不要用“__line__”。

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;

相关文章推荐

linux c inline

转自:http://hi.baidu.com/beibeiboo/blog/item/cbea8c03191c027e3812bb72.html 看kernel,随处可见inline.说实话,还没写...

用户进程到系统调用

1.用户进程使用如open();的C库函数。 2从库函数(open)中使用"int 0x80"或是syscall命令进入system_call。 glibc 中的部分源码 /...

ARM Linux系统调用的原理

ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交互提供了一组接口。在应用程序和硬件之间设置一个额外层具有很多优点。首先,这使得编程更加容易,把用户从学习硬件设备的低级编...

static inline func 内联函数

static inline function是干嘛的? 如果你的.m文件需要频繁调用一个函数,可以用static inline来声明,这相当于把函数体当做一个大号的宏定义.不过这也不是百分之...

内联函数---Inline Function

影响性能的一个重要因素是内联技巧。内联函数也可称为内嵌函数。 在C++中,函数调用需要建立栈环境,进行参数复制,保护调用现场,返回时,还要进行返回值复制,恢复调用现场。这些工作都是与完成特定任务的操作...

inline内联函数

inline函数的由来   首先,inline函数也是一种函数,那么我们首先讲讲函数的作用?在现实生活中如果我们自己想单独完成某项大的工作的话几乎是不可能的,肯定会需要其他人的帮助,我们会告诉帮助...

iOS OC内联函数 inline

inline在iOS中的一些框架中,static inline是经常出现的关键字组合.static自不用多说,表示在当前文件中应用,如 static A, 在其它文件中也可以出现static A.不会...

C/C++内联函数(inline)

C/C++提供了内联函数这个机制。 内联函数是向编译器建议:编译这个函数的时候直接把函数展开,而不是进行函数调用。但是这只是一个建议,编译器可能并不接受这个建议,仍然把它当做普通函数进行编译。 合理使...

C++学习笔记(二):内联函数inline

一般来说,当我们定义一个函数以后,编译器就会在内存中为其创建一个指令集,当我们调用这个函数时,程序就会跳转到该指令集处。当该函数运行完毕后,程序又会返回到原来执行调用该函数的下一行继续执行。假如对该函...

C++中 内联函数(关键字:inline)

 引入内联函数的目的是为了解决程序中函数调用的效率问题。     函数是一种更高级的抽象。它的引入使得编程者只关心函数的功能和使用方法,而不必关心函数功能的具体实现;函数的引入可以减少程序的目...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)