_attribute__ 之weak,alias属性

//strong.c

#include <stdio.h>

void symbol1()
{
    printf("%s.%s\n",__FILE__,__FUNCTION__);
}
//weak.c

#include <stdio.h>
void symbol1() __attribute__ ((weak,alias("symbol222")));
//void symbol1() __attribute__ ((weak));
void symbol222()
{
    printf("%s.%s\n",__FILE__,__FUNCTION__);
}

int main()
{
    //asm(".weak symbol1\n\t .set symbol1, symbol222\n\t");
    if(symbol1)
 symbol1();
    return 0;
}
////////////////////////////////////////
//gcc weak.c strong.c -o weak
//./weak
//输出:strong.c.symbol1
////////////////////////////////////////
//gcc weak.c -o weak
//./weak
//输出:weak.c.symbol222
////////////////////////////////////////
//总结weak属性
//(1)asm(".weak symbol1\n\t .set symbol1, symbol222\n\t");与
//     void symbol1() __attribute__ ((weak,alias("symbol222")));等效。
//(2)给函数加上weak属性时,即使函数没定义,函数被调用也可以编译成功。
//(3)当有两个函数同名时,则使用强符号(也叫全局符号,即没有加weak的函数)来代替弱符号(加weak的函数)。
//(4)当函数没有定义,但如果是“某个函数”的别名时,如果该函数被调用,就间接调用“某个函数”。

 

 

  • __attribute__
            __attribute__(section),用来修饰函数时,可以使你把代码放在image的不同段,如:
            void
            f(void)
            __attribute__((section(“new_section”)));函数f()将被放到只读new_section段中,而不是.text中。
            __attribute((regparm(0))),表示不从寄存器中传递参数,如果是regparm(3)则调用函数的时候参数不是通过栈传递,而是直接放到寄存器里,被调用函数直接从寄存器取参数。gcc编译器在汇编过程中调用c语言函数时传递参数有两种方法:一种是通过堆栈,另一种是通过寄存器,缺省使用寄存器,假如想通过堆栈传递,定义的c函数时要在函数前加上宏asmlinkage
           
  • asmlinkage
            在看内核源代码start_kernel函数时,第一个遇到的疑问是asmlinkage,原来asmlinkage是一个宏,它定义在文件include/asm-i386/linkage.h中,具体如下:
            #define
            asmlinkage CPP_ASMLINKAGE
            __attribute__((regparm(0))),其中CPP_ASMLINKAGE也是一个宏,定义在include/linux/linkage.h头文件中,具体为:
           
           
            #define
            CPP_ASMLINKAGE extern "C",extern
            “C”是用来实现C++和C的混合编程,而__attribute__是关键字,是gcc的C语言扩展,它可以设置函数属性(Function
            Attribute)、变量属性(Variable
            Attribute)和类型属性(Type
            Attribute),总的来说,asmlinkage是个宏,使用它是为了保持参数在stack中,因为从汇编语言到C语言代码参数的传递是通过stack的,它也可能从stack中得到一些不需要的参数,asmlinkage将要解析那些参数。
           
  • __init是一个宏定义,定义在arch/um/include/init.h文件中,具体如:
            #define
            __init          __attribute__ ((__section__ (".init.text")))
           
           
            这个标志符和函数声明放在一起,它表示gcc编译器在编译的时候需要把这个函数放在.init.text中,而这个section在内核完成初始化之后会被释放掉。
           
  • __weak是一个宏定义,定义在include/asm-mips/linkage.h文件中,具体如:#define
            __weak __attribute__((weak)),它常用于函数和变量的声明和函数的定义,是GNU
            compiler的扩展,被ARM
            compiler支持,可以将一个函数声明为weak,
            当没有其他同名函数声明时调用weak,
            有其他同名函数时调用其他同名函数。
           
  • __va(x)        是个宏,定义在include/asm-alpha/page.h文件中,具体如下:
            #define
            __va(x)  ((void *)((unsigned long)(x) + PAGE_OFFSET))
            __pa(x)也是个宏,定义在include/asm-alpha/page.h文件中,具体如下:
            #define
            __pa(x) ((unsigned
            long)(x)-PAGE_OFFSET),其中的PAGE_OFFSET定义为0xffff800000000000UL或0xfffffc0000000000UL
           
  • register可以用来修饰变量,表示寄存器变量,只能用于整型和字符变量,表示变量被存储在CPU的寄存器中,而不像普通变量被存储在内存中,这样可以提高运算速度,它常用于在同一变量名频繁出现的地方,且它只适用于局部变量和函数的形式参数,它属于auto型变量,不能作为全局变量
           
  • EXPORT_SYMBOL:若内核函数或变量要被内核模块调用,则必须使用EXPORT_SYMBOL宏进行处理,作用之一是将该符号连接到二进制文件的各个__ksymtab_xx_xx
            section,内核加载模块时,会先确认该模块调用的各内核函数是否已export,也就是说EXPORT_SYMBOL可以将一个函数或变量以符号的方式导出给其他模块使用。

     

/******************** (C) COPYRIGHT 2007 STMicroelectronics ******************** * File Name : stm32f10x_vector.c * Author : MCD Application Team * Version : V1.0 * Date : 10/08/2007 * Description : This file contains the vector table for STM32F10x. * After Reset the Cortex-M3 processor is in Thread mode, * priority is Privileged, and the Stack is set to Main. ******************************************************************************** * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. *******************************************************************************/ /* Includes ------------------------------------------------------------------*/ void NMIException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void HardFaultException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void MemManageException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void BusFaultException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void UsageFaultException(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DebugMonitor(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SVCHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void PendSVC(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SysTickHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); /* Peripherals handlers */ void WWDG_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void PVD_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TAMPER_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void RTC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void FLASH_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void RCC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI0_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI4_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel4_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel5_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel6_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void DMAChannel7_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void ADC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USB_HP_CAN_TX_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USB_LP_CAN_RX0_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void CAN_RX1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void CAN_SCE_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI9_5_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_BRK_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_UP_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_TRG_COM_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM1_CC_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void TIM4_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C1_EV_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C1_ER_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C2_EV_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void I2C2_ER_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SPI1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void SPI2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USART1_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USART2_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USART3_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void EXTI15_10_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void RTCAlarm_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); void USBWakeUp_IRQHandler(void) __attribute__ ((weak, alias("IntDefaultHandler"))); /* Exported types ------------------------------------------------------------*/ /* Exported constants --------------------------------------------------------*/ extern unsigned long _etext; extern unsigned long _sidata; /* start address for the initialization values of the .data section. defined in linker script */ extern unsigned long _sdata; /* start address for the .data section. defined in linker script */ extern unsigned long _edata; /* end address for the .data section. defined in linker script */ extern unsigned long _sbss; /* start address for the .bss section. defined in linker script */ extern unsigned long _ebss; /* end address for the .bss section. defined in linker script */ extern void _estack; /* init value for the stack pointer. defined in linker script */ /* Private typedef -----------------------------------------------------------*/ /* function prototypes -------------------------------------------------------*/ void Reset_Handler(void) __attribute__((__interrupt__)); extern int main(void); /******************************************************************************* * * The minimal vector table for a Cortex M3. Note that the proper constructs * must be placed on this to ensure that it ends up at physical address * 0x0000.0000. * *******************************************************************************/ __attribute__ ((section(".vectors"), used)) void (* const gVectors[])(void) = { (void (*)(void))((unsigned long)&_estack), // The initial stack pointer Reset_Handler, // The reset handler NMIException, HardFaultException, MemManageException, BusFaultException, UsageFaultException, 0, 0, 0, 0, /* Reserved */ SVCHandler, DebugMonitor, 0, /* Reserved */ PendSVC, SysTickHandler, WWDG_IRQHandler, PVD_IRQHandler, TAMPER_IRQHandler, RTC_IRQHandler, FLASH_IRQHandler, RCC_IRQHandler, EXTI0_IRQHandler, EXTI1_IRQHandler, EXTI2_IRQHandler, EXTI3_IRQHandler, EXTI4_IRQHandler, DMAChannel1_IRQHandler, DMAChannel2_IRQHandler, DMAChannel3_IRQHandler, DMAChannel4_IRQHandler, DMAChannel5_IRQHandler, DMAChannel6_IRQHandler, DMAChannel7_IRQHandler, ADC_IRQHandler, USB_HP_CAN_TX_IRQHandler, USB_LP_CAN_RX0_IRQHandler, CAN_RX1_IRQHandler, CAN_SCE_IRQHandler, EXTI9_5_IRQHandler, TIM1_BRK_IRQHandler, TIM1_UP_IRQHandler, TIM1_TRG_COM_IRQHandler, TIM1_CC_IRQHandler, TIM2_IRQHandler, TIM3_IRQHandler, TIM4_IRQHandler, I2C1_EV_IRQHandler, I2C1_ER_IRQHandler, I2C2_EV_IRQHandler, I2C2_ER_IRQHandler, SPI1_IRQHandler, SPI2_IRQHandler, USART1_IRQHandler, USART2_IRQHandler, USART3_IRQHandler, EXTI15_10_IRQHandler, RTCAlarm_IRQHandler, USBWakeUp_IRQHandler, 0, 0, 0, 0, 0, 0, 0, (unsigned short)0xF108F85F //this is a workaround for boot in RAM mode. }; /******************************************************************************* * Function Name : Reset_Handler * Description : This is the code that gets called when the processor first * starts execution following a reset event. Only the absolutely * necessary set is performed, after which the application * supplied main() routine is called. * Input : * Output : * Return : *******************************************************************************/ void Reset_Handler(void) { unsigned long *pulSrc, *pulDest; // // Copy the data segment initializers from flash to SRAM. // pulSrc = &_sidata; for(pulDest = &_sdata; pulDest < &_edata; ) { *(pulDest++) = *(pulSrc++); } // // Zero fill the bss segment. // for(pulDest = &_sbss; pulDest < &_ebss; ) { *(pulDest++) = 0; } // // Call the application's entry point. // main(); } void IntDefaultHandler(void) { for(;;); } /****************** (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/ 这段代码有什么作用
最新发布
11-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值