linux内核源码中常见宏标志tag

http://www.examda.com/linux/fudao/20100330/094653772.html

  这些宏包括 __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
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(651) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~
评论热议
### 回答1: 要在VSCode中查看Linux内核源码,需要先安装C/C++插件和Remote-SSH插件。然后,使用Remote-SSH插件连接到Linux服务器,将内核源码复制到本地,再在VSCode中打开源码文件夹即可。可以使用VSCode的代码导航、代码高亮、代码补全等功能方便地查看和编辑内核源码。 ### 回答2: 在VSCode中查看Linux内核源码是可能的,但是由于Linux内核源码是庞大而复杂的,直接查看可能会导致编辑器负载过重或执行效率低下。所以,建议采用以下步骤来配置VSCode来查看Linux内核源码。 首先,确保已经在本地安装了Git和VSCode以及之前配置了SSH密钥。 1. 克隆Linux内核源码库:在终端中运行以下命令克隆Linux源码库: ``` git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git ``` 2. 打开VSCode并安装"C/C++"插件:在左侧的Extensions图标处搜索并安装"C/C++"插件。 3. 打开内核源码文件夹:点击VSCode左上角的“文件”->“打开文件夹”,选择Linux内核源码库的根文件夹。 4. 设置编译器路径:点击VSCode左下角的"设置"图标,在搜索栏中输入"C_Cpp: Default",找到 "C_Cpp: Default: Compiler Path" 选项并配置为你本地的C/C++编译器路径。例如,GCC编译器的路径可以是 "/usr/bin/gcc"。 5. 配置调试器:点击VSCode左侧的调试器图标,在对话框顶部选择"生成",然后选择 "C++ (GDB/LLDB)"。在生成配置文件中添加以下内容: ```json "program": "${workspaceFolder}/vmlinux", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true } ] ``` 6. 配置任务:点击VSCode左侧的调试器图标,在右上角找到“配置(齿轮)”图标,点击后选择 "任务设置",然后选择 "任务配置"。在生成任务文件中添加以下内容: ```json "tasks": [ { "label": "linux-build", "type": "shell", "command": "make", "args": [ "menuconfig" ], "group": { "kind": "build", "isDefault": true } } ] ``` 7. 开始使用:现在,你可以在VSCode中导航、查看和编辑Linux内核的源代码。你可以使用Ctrl + 点击或按F12来跳转到函数或变量的定义,使用Ctrl + 左键单击来跳转到引用等。 需要注意的是,由于Linux内核源码的复杂性,初学者可能需要花费一些时间来了解和适应源码的结构和架构。 ### 回答3: 要在VSCode中查看Linux内核源码,首先需要进行一些设置和准备工作: 1. 安装VSCode:前往VSCode官方网站下载并安装适用于你的操作系统的VSCode。 2. 安装C/C++插件:在VSCode的插件商店中搜索并安装C/C++插件。 3. 安装GCC和GDB:确保你的Linux系统上已经安装了GCC(GNU C Compiler)和GDB(GNU Debugger)。 4. 下载Linux内核源码:前往Linux内核官方网站或者GitHub仓库下载所需版本的Linux内核源码。 安装完成后,可以按照以下步骤在VSCode中查看Linux内核源码: 1. 打开VSCode,并在左侧的导航栏中选择文件 -> 打开文件夹,选择你下载的Linux内核源码文件夹。 2. 配置C/C++插件:点击VSCode左下角的齿轮图标,选择“设置”,在搜索框中输入“c_cpp”的关键字,找到C/C++插件相关的设置选项。 3. 配置编译器和调试器:在设置中找到“C_Cpp: Default:Compiler Path”选项,并将其设置为你的GCC编译器的路径,类似于“/usr/bin/gcc”。然后找到“C_Cpp:Default:Debugger”选项,并将其设置为你的GDB调试器的路径,类似于“/usr/bin/gdb”。 4. 配置代码导航:在设置中找到“C_Cpp: Tag Parser”选项,并将其设置为“CTags”或“gcc”来启用代码导航功能。 5. 开始浏览代码:在VSCode的左侧导航栏中浏览打开的Linux内核源码文件夹,你可以使用代码编辑、跳转和调试等功能来查看和理解Linux内核的源代码。 通过以上步骤,你可以在VSCode中方便地查看和分析Linux内核源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值