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 */

/* ld script to make ARM Linux kernel
* taken from the i386 version by Russell King
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/

#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
#include <asm/memory.h>

OUTPUT_ARCH(arm)
ENTRY(stext)

#ifndef __ARMEB__
jiffies = jiffies_64;
#else
jiffies = jiffies_64 + 4;
#endif

SECTIONS
{
#ifdef CONFIG_XIP_KERNEL
. = XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR);
#else
. = PAGE_OFFSET + TEXT_OFFSET;
#endif
.text.head : {
_stext = .;
_sinittext = .;
*(.text.head)
}

.init : { /* Init code and data */
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 = .;
INITCALLS
__initcall_end = .;
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
__security_initcall_start = .;
*(.security_initcall.init)
__security_initcall_end = .;
#ifdef CONFIG_BLK_DEV_INITRD
. = ALIGN(32);
__initramfs_start = .;
usr/built-in.o(.init.ramfs)
__initramfs_end = .;
#endif
. = ALIGN(4096);
__per_cpu_load = .;
__per_cpu_start = .;
*(.data.percpu.page_aligned)
*(.data.percpu)
*(.data.percpu.shared_aligned)
__per_cpu_end = .;
#ifndef CONFIG_XIP_KERNEL
__init_begin = _stext;
INIT_DATA
. = ALIGN(4096);
__init_end = .;
#endif
}

/DISCARD/ : { /* Exit code and data */
EXIT_TEXT
EXIT_DATA
*(.exitcall.exit)
*(.ARM.exidx.exit.text)
*(.ARM.extab.exit.text)
#ifndef CONFIG_MMU
*(.fixup)
*(__ex_table)
#endif
}

.text : { /* Real text segment */
_text = .; /* Text and read-only data */
__exception_text_start = .;
*(.exception.text)
__exception_text_end = .;
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
KPROBES_TEXT
#ifdef CONFIG_MMU
*(.fixup)
#endif
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
*(.got) /* Global offset table */
}

RODATA

_etext = .; /* End of text and rodata section */

#ifdef CONFIG_ARM_UNWIND
/*
* Stack unwinding tables
*/
. = ALIGN(8);
.ARM.unwind_idx : {
__start_unwind_idx = .;
*(.ARM.exidx*)
__stop_unwind_idx = .;
}
.ARM.unwind_tab : {
__start_unwind_tab = .;
*(.ARM.extab*)
__stop_unwind_tab = .;
}
#endif

#ifdef CONFIG_XIP_KERNEL
__data_loc = ALIGN(4); /* location in binary */
. = PAGE_OFFSET + TEXT_OFFSET;
#else
. = ALIGN(THREAD_SIZE);
__data_loc = .;
#endif

.data : AT(__data_loc) {
_data = .; /* address in memory */

/*
* first, the init task union, aligned
* to an 8192 byte boundary.
*/
*(.data.init_task)

#ifdef CONFIG_XIP_KERNEL
. = ALIGN(4096);
__init_begin = .;
INIT_DATA
. = ALIGN(4096);
__init_end = .;
#endif

. = ALIGN(4096);
__nosave_begin = .;
*(.data.nosave)
. = ALIGN(4096);
__nosave_end = .;

/*
* then the cacheline aligned data
*/
. = ALIGN(32);
*(.data.cacheline_aligned)

/*
* The exception fixup table (might need resorting at runtime)
*/
. = ALIGN(32);
__start___ex_table = .;
#ifdef CONFIG_MMU
*(__ex_table)
#endif
__stop___ex_table = .;

/*
* and the usual data section
*/
DATA_DATA
CONSTRUCTORS

_edata = .;
}
_edata_loc = __data_loc + SIZEOF(.data);

.bss : {
__bss_start = .; /* BSS */
*(.bss)
*(COMMON)
_end = .;
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}

/*
* These must never be empty
* If you have to comment these two assert statements out, your
* binutils is too old (for other reasons as well)
*/
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")

可以发现__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

转载于:https://www.cnblogs.com/hoys/archive/2011/03/30/2000299.html

__init和__initdata相关推荐

  1. 关于__init、__initdata和__exit、__exitdata的学习笔记

    由于4年前对于C语言和Linux的知识贫乏,所以当时对于模块中的函数定义没有细看.这次在温习<LDD3>的时候,重新看了一下关于__init.__initdata和__exit.__exi ...

  2. __attribute__编绎属性、关于__init、__initdata、__exit、__exitdata及类似的宏、关于initcall的一些宏定义、__setup宏的来源及使用...

    1. gcc的__attribute__编绎属性 要了解Linux Kernel代码的分段信息,需要了解一下gcc的__attribute__的编绎属性,__attribute__主要用于改变所声明或 ...

  3. __init、__initdata和__exit、__exitdata

    由于4年前对于C语言和Linux的知识贫乏,所以当时对于模块中的函数定义没有细看.这次在温习<LDD3>的时候,重新看了一下关于__init.__initdata和__exit.__exi ...

  4. 内核中_init,_exit中的作用

    __init, __initdata等属性标志,是要把这种属性的代码放入目标文件的.init.text节,数据放入.init.data节──这一过程是通过编译内核时为相关目标平台提供了xxx.lds链 ...

  5. Linux下TI omap芯片 MUX 配置分析(以AM335X芯片为例)

    在移植内核的时候,通常会遇到引脚复用(MUX)的配置问题.在现在的Linux内核中,对于TI的ARM芯片,早已经有了比较通用的MUX配置框架.这对于许多TI的芯片都是通用的,这次看AM335X的代码顺 ...

  6. linux 禁用 内核 驱动程序,Linux设备驱动程序学习----5.模块的初始化和关闭

    模块的初始化和关闭 1. 初始化函数 模块的初始化函数负责注册模块所提供的任何设施,即可以被应用程序访问的新功能,可能是一个完整的驱动程序或者仅仅是一个新的软件抽象.初始化函数的定义通常如下所示: s ...

  7. linux设备驱动读书笔记

    linux设备驱动读书笔记 设备驱动简介 机制:提供什么能力 策略:如何使用这些能力 在编写驱动时, 程序员应当编写内核代码来存取硬件, 但是不能强加特别的策略给用户, 因为不同的用户有不同的需求. ...

  8. 安卓 体验linux mux,Linux下TI omap芯片 MUX 配置分析(以AM335X芯片为例)

    对于许多TI的芯片来说,引脚复用的配置是在Control Module(配置模块)的寄存器里配置的,(这个和三星的CPU有点不同,三星的一般在GPIO的寄存器中配置).所以当你需要配置这些寄存器的时候 ...

  9. linux设备驱动读书笔记(转)

    linux设备驱动读书笔记 设备驱动简介 机制:提供什么能力 策略:如何使用这些能力 在编写驱动时, 程序员应当编写内核代码来存取硬件, 但是不能强加特别的策略给用户, 因为不同的用户有不同的需求. ...

最新文章

  1. 20年老码农分享20条编程经验,你pick哪些?
  2. Nor 与Nand Flash 区别
  3. 人脸检测发展:从VJ到深度学习(下)
  4. # 异运算_小学六年级数学知识点总结-03分数的混合运算
  5. 深度学习如何验证自己的想法
  6. apache spark_Apache Spark:更改架构之前必须解决的5个陷阱
  7. Spring Boot : ApplicationListner
  8. 初识Opserver,StackExchange的监控解决方案
  9. 对+=赋值运算符的认识
  10. xg push sdk android,AppCan文档中心-uexXGPush
  11. 小程序源码:全新外卖侠cps5.6全套微信小程序源码下载(内附加2.7.5版本微擎)支持多种CPS收益和流量主收益
  12. uniapp App端 实现pdf文件预览
  13. Android CardView 不显示阴影
  14. python如何读取txt文件内容
  15. Python Basic - Python open() 、closed()、write()、read()、 readline()、readlines()、with与文件进行交互
  16. php 匹配图片加上域名,20170321_正则表达式:匹配图片地址,添加域名
  17. 从平安普惠捆绑意外险,看最强金融生存法则:底子厚、路子野、扛得住
  18. PasteSpider的下载和安装
  19. 电脑录音软件哪个好,怎么用电脑录音
  20. Java并发编程系列之九:AQS

热门文章

  1. C++_类和对象_C++继承_多继承语法---C++语言工作笔记067
  2. STM32工作笔记0083---UCOSIII中断和时间管理
  3. 微信公众开放平台开发08---纯java 实现微信开发:编写自定义菜单
  4. SQL 中having 和where的区别(转)
  5. MongoDB 我的学习笔记
  6. setsockopt()改善程序的健壮性
  7. JAVA redis 常用函数
  8. 随想录(被高估的busybox)
  9. submit+php语法报错,PHP语法基础部分
  10. mysqli 语句和mysql语句一样吗_如何为动态sql语句准备mysqli语句