代码中看见:#define _fastcall

所以了解下fastcall

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Linux内核中的fastcall和asmlinkage宏

[日期:2012-12-31] 来源:Linux社区  作者:ce123 [字体:  ]
 

Linux内核版本:2.6.14

在linux内核中我们都会经常见到FASTCALL和armlinkage,它们各有什么不同呢?下面我们来具体分析一下。

在标准C系中函数的形参在实际传入参数的时候会涉及到参数存放的问题,那么这些参数存放在哪里呢?对x86比较了解的话,应该知道这些函数参数和函数内部局部变量一起被分配到了函数的局部堆栈中。linux操作系统支持多种CPU架构,比如x86、ppc和arm等,在不同的处理器结构上不能保证都是通过 局部栈传递参数的。ARM对函数调用过程中的传参定义了一套规则,即 ATPCS,规则中明确指出ARM中R0-R4都是作为通用寄存器使用,在函数调用时处理器从R0-R4中获取参数,在函数返回时再 将需要返回的参数一次存到R0-R4中,也就是说可以将函数参数直接存放在寄存器中,所以为了严格区别函数参数的存放位置,引入了两个标记,即 asmlinkage和FASTCALL,前者表示将函数参数存放在局部栈中,后者则是通知编译器将函数参数用寄存器保存起来。

1.x86平台

#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))
#define FASTCALL(x) x __attribute__((regparm(3)))
#define fastcall __attribute__((regparm(3)))

函数定义前加宏asmlinkage,表示这些函数通过堆栈而不是通过寄存器传递参数。gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器。缺省时采用寄存器,假如你要在你的汇编过程中调用c语言函数,并且想通过堆栈传递参数,你定义的c函数时要在函数前加上宏asmlinkage。

其中 __attribute__是关键字,是gcc的c语言扩展。__attribute__机制是GNU C的一大特色,它可以设置函数属性、变量属性和类型属性等。可以通过它们向编译器提供更多数据,帮助编译器执行优化等。

__attribute__((regparm(0))):告诉gcc编译器该函数不需要通过任何寄存器来传递参数,参数只是通过堆栈来传递。

__attribute__((regparm(3))):告诉gcc编译器这个函数可以通过寄存器传递多达3个的参数,这3个寄存器依次为EAX、EDX 和 ECX。更多的参数才通过堆栈传递。这样可以减少一些入栈出栈操作,因此调用比较快。

asmlinkage大都用在系统调用中。有一些情况下是需要明确的告诉编译器,我们是使用stack来传递参数的,比如x86中的系统调用,是先将参数压入stack以后调用sys_*函数的,所以所有的sys_*函数都有asmlinkage来告诉编译器不要使用寄存器来编译。

2.arm平台

对于arm处理器的<asm/linkage.h>,没有定义FASTCALL和armlinkage,所以没有意义(对于ARM平台来说,要符合ATPCS过程调用标准,即通过寄存器传递的。ARM中R0-R4用于存放传入参数,所有函数的参数不应该大于5个,如果超过5个,多余的参数被存放到局部栈中。)。

#ifndef FASTCALL
#define FASTCALL(x) x
#define fastcall
#endif

#ifndef asmlinkage
#define asmlinkage CPP_ASMLINKAGE
#endif

3.CPP_ASMLINKAGE

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

extern "C" 包含双重含义,从字面上即可得到:首先,被它修饰的目标是“extern”的;其次,被它修饰的目标是“C”的。

  (1) 被extern "C"限定的函数或变量是extern类型的extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。与extern对应的关键字是static,被它修饰的全局变量和函数只能在本模块中使用。因此,一个函数或变量只可能被本模块使用时,其不可能被extern “C”修饰。

  (2) 被extern "C"修饰的变量和函数是按照C语言方式编译和连接的。

Linux内核中的fastcall和asmlinkage宏的更多相关文章

  1. Linux 内核中 likely 与 unlikely 的宏定义解析

    在 2.6 内核中,随处能够见到 likely() 和 unlikely() 的身影,那么为什么要用它们?它们之间有什么差别? 首先要明白: if(likely(value)) 等价于 if(valu ...

  2. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析【转】

    转自:http://blog.csdn.net/hzn407487204/article/details/7995041 在驱动程序里, ioctl() 函数上传送的变量 cmd 是应用程序用于区别设 ...

  3. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法与解析

    ref from : http://blog.csdn.net/zhuxiaoping54532/article/details/49680537 main 在驱动程序里, ioctl() 函数上传送 ...

  4. Linux内核中_IO,_IOR,_IOW,_IOWR宏的用法

    #define _IO(type,nr)        _IOC(_IOC_NONE,(type),(nr),0) #define _IOR(type,nr,size)    _IOC(_IOC_RE ...

  5. (十)Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  6. Linux内核中的常用宏container_of

    Container_of在Linux内核中是一个常用的宏,用于从包含在某个结构中的指针获得结构本身的指针,通俗地讲就是通过结构体变量中某个成员的首地址进而获得整个结构体变量的首地址. Containe ...

  7. Linux内核中的常用宏container_of其实很简单【转】

    转自:http://blog.csdn.net/npy_lp/article/details/7010752 开发平台:Ubuntu11.04 编 译器:gcc version 4.5.2 (Ubun ...

  8. linux内核中的宏ffs(x)

    linux内核中ffs(x)宏是平台相关的宏,在arm平台,该宏定义在 arch/arm/include/asm/bitops.h #define ffs(x) ({ unsigned long __ ...

  9. 剖析linux内核中的宏---------container_of

    #define container_of(ptr, type, member) ({ \ const typeof(((type *)0)->member) * __mptr = (ptr); ...

随机推荐

  1. ibatis 到 MyBatis区别(zz)

    简介: 本文主要讲述了 iBatis 2.x 和 MyBatis 3.0.x 的区别,以及从 iBatis 向 MyBatis 移植时需要注意的地方.通过对本文的学习,读者基本能够了解 MyBatis ...

  2. Activiti6.0 安装出错 log4j:ERROR setFile(null,true) call failed.

    由于要选择一款合适的流程引擎,需要在jbpm和Activiti之间做对比,我这边负责Activiti的测试. 看到Activiti官网(http://www.activiti.org/download ...

  3. [MetaHook] Quake FMOD function

    QFMOD.h #ifndef QFMOD_H #define QFMOD_H #include "fmod.h" extern FMOD_RESULT (F_API *qFMOD ...

  4. [BZOJ 1085][SCOI2005]骑士精神(IDA*)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1085 分析: 首先第一感觉是宽搜,但是空间需要8^15*5*5,明显不够,又鉴于最大深 ...

  5. [wikioi2069]油画(贪心)

    题目:http://www.wikioi.com/problem/2069/ 分析: 首先这个问题比较复杂,涉及到两个重要的考虑点,一个是当前拿来的颜色是否保留,一个是若保留后那么应该把当前盘子的哪个 ...

  6. CSharpThinking---C#版本总结(附加三)

    C#版本总结: 日期 框架.net Visual Studio C# CLR 2002.2  1.0 2002 1.0 1.0 2003.4  1.1 2003 1.2 1.1 2005.11  2. ...

  7. MySQL配置

    一.登录MySQL 要登录到MySQL只需要使用如下命令. mysql -h localhost -u root -p localhost:IP地址: root:用户名: database:数据库名( ...

  8. 小记:事务(进程 ID 56)与另一个进程被死锁在 锁 | 通信缓冲区 资源上,并且已被选作死锁牺牲品。

    今天在做SQL并发UPDATE时遇到一个异常:(代码如下) //Parallel 类可产生并发操作(即多线程) Parallel.ForEach(topics, topic => { //DBH ...

  9. Task.Run Vs Task.Factory.StartNew

    在.Net 4中,Task.Factory.StartNew是启动一个新Task的首选方法.它有很多重载方法,使它在具体使用当中可以非常灵活,通过设置可选参数,可以传递任意状态,取消任务继续执行,甚至 ...

  10. JSP/SERVLET入门教程--Servlet 使用入门

    现在的JSP书籍有的是直接讲述JSP的使用,然后再讲解SERVERLET的使用;也有书籍是先讲述SERVERLET的使用,然后讲解JSP使用.个人认为第二种相对好一些,至于原因大家可以在学习体会到!所 ...