这些宏包括 __init、__initdata、__initfunc()、asmlinkage、ENTRY()、FASTCALL()等等。它们的定义主要位于 Include\linux\linkage.h和 include\asm-i386\Init.h以及其他一些.h文件中。

  1) __init位置:include\asm-i386\Init.h

  定义:#define __init __attribute__ ((__section__ (".text.init")))

  注释:这个标志符和函数声明放在一起,表示gcc编译器在编译的时候需要把这个函数放.text.init section中,而这个section在内核完成初始化之后,会被释放掉。

  举例:asmlinkage void __init start_kernel(void){...}

  2) __initdata

  位置:include\asm-i386\Init.h

  定义:#define __initdata __attribute__ ((__section__ (".data.init")))

  注释:这个标志符和变量声明放在一起,表示gcc编译器在编译的时候需要把这个变量放在.data.init section中,而这个section在内核完成初始化之后,会被释放掉。

  举例:static struct kernel_param raw_params[] __initdata = {....}

  3) __initfunc()

  位置:include\asm-i386\Init.h

  定义: #define __initfunc(__arginit) \

  __arginit __init; \

  __arginit

  注释: 这个宏用来定义一个 __init 函数。

  举例: __initfunc(void mem_init(unsigned long start_mem, unsigned long e

  nd_mem)) {....}

  4) asmlinkage

  位置:Include\linux\linkage.h

  定义:#define asmlinkage CPP_ASMLINKAGE __attribute__((regparm(0)))

  注释:这个标志符和函数声明放在一起,告诉gcc编译器该函数不需要通过任何寄存器来传递参数,参数只是通过堆栈来传递。



  举例:asmlinkage void __init start_kernel(void){...}

  5) ENTRY()

  位置:Include\linux\linkage.h

  定义: #define ENTRY(name) \

  .globl SYMBOL_NAME(name); \

  ALIGN; \

  SYMBOL_NAME_LABEL(name)

  注释: 将name声明为全局,对齐,并定义为标号。

  举例: ENTRY(swapper_pg_dir)

  .long 0x00102007

  .fill __USER_PGD_PTRS-1,4,0

  /* default: 767 entries */

  .long 0x00102007

  /* default: 255 entries */

  .fill __KERNEL_PGD_PTRS-1,4,0

  等价于

  .globl swapper_pg_dir

  .align 16,0x90


  /* if i486 */

  swapper_pg_dir:

  .long 0x00102007

  .fill __USER_PGD_PTRS-1,4,0

  /* default: 767 entries */

  .long 0x00102007

  /* default: 255 entries */

  .fill __KERNEL_PGD_PTRS-1,4,0

  6) FASTCALL()

  位置:Include\linux\kernel.h

  定义:#define FASTCALL(x) x __attribute__((regparm(3)))

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

  举例:extern void FASTCALL(__switch_to(struct task_struct *prev, struct t

  ask_struct *next));

  这个例子中,prev将通过eax,next通过edx传递

  7)_sched 存在于kernel/sched.h文件中

  Attach to any functions which should be ignored in wchan output

  #define _sched _attribute_ ((_section_(".sched.text")))

  Reference:



​http://blog.chinaunix.net/u2/60011/showart_1010485.html​

__init和__initdata


Linux在arch/$(ARCH)/kernel/vmlinux.lds中定义了.init段。__init和__initdata属性的数据都在这个段中,当内核启动完毕后,这个段中的内存会被释放掉供其他使用。


__init和__initdata宏定义如下:

/* include/linux/init.c */

#define __init  __attribute__ ((__section__ (".init.text")))

#define __initdata __attribute__ ((__section__ (".init.data")))


vmlinux.lds内容如下:

/* arch/arm/kernel/vmlinux.lds */

OUTPUT_ARCH(arm)

ENTRY(stext)

jiffies = jiffies_64;

SECTIONS

{

. = (0xc0000000) + 0x00008000;

.init : { /* Init code aand data  */

  _stext = .;

   _sinittext = .;

   *(.init.text)

   _einittext = .;

  __proc_info_begin = .;

   *(.proc.info.init)

  __proc_info_end = .;

  __arch_info_begin = .;

   *(.arch.info.init)

  __arch_info_end = .;

  __tagtable_begin = .;

   *(.taglist.init)

  __tagtable_end = .;

  . = ALIGN(16);

  __setup_start = .;

   *(.init.setup)

  __setup_end = .;

  __early_begin = .;

   *(.early_param.init)

  __early_end = .;

  __initcall_start = .;

   *(.initcall1.init)

   *(.initcall2.init)

   *(.initcall3.init)

   *(.initcall4.init)

   *(.initcall5.init)

   *(.initcall6.init)

   *(.initcall7.init)

  __initcall_end = .;

  __con_initcall_start = .;

   *(.con_initcall.init)

  __con_initcall_end = .;

  __security_initcall_start = .;

   *(.security_initcall.init)

  __security_initcall_end = .;

  . = ALIGN(32);

  __initramfs_start = .;

   usr/built-in.o(.init.ramfs)

  __initramfs_end = .;

  . = ALIGN(64);

  __per_cpu_start = .;

   *(.data.percpu)

  __per_cpu_end = .;

  __init_begin = _stext;

  *(.init.data)

  . = ALIGN(4096);

  __init_end = .;

}

……

}

可以发现__init对应的section(.init.text)和__initdata对应的section(.init.data)都在.init 段中。同样,这里定义的其他一些section也都会在使用完后被释放,如.init.setup,.initcall1.init等。

释放memory的大小会在系统启动过程中打印出来:

eth0: link up

IP-Config: Complete:

      device=eth0, addr=192.168.167.15, mask=255.255.255.0, gw=192.168.167.254,

     host=192.168.167.15, domain=, nis-domain=(none),

     bootserver=192.168.167.170, rootserver=192.168.167.170, rootpath=

Looking up port of RPC 100003/2 on 192.168.167.170

Looking up port of RPC 100005/1 on 192.168.167.170

VFS: Mounted root (nfs filesystem).

Freeing init memory: 128K