首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

在 Linux on POWER 上利用透明大内存页(3)执行体内的段

在 Linux on POWER 上利用透明大内存页(3)执行体内的段

开始之前,我们先来看看在所生成的执行体中包含的段。我会通过一个简单的 C 程序加以演示。在如下的示例中,我将声明一个大型的未初始化的数组和一个大型的已经初始化了的数组。
显示了称为        sections.c 的源文件。
清单 1. sections.c 源文件
1
2
3
4
5
6
7
8
9
10
#define ELEMENTS 1024*1024
static double  bss_array[ELEMENTS];
static double  data_array[ELEMENTS] = {5.0};
     
int   main()   {
    int   i;   
    for (i = 1; i < ELEMENTS; i++) {
       bss_array    = data_array;
    }
}




bss 数组和 data 数组的主要区别很容易在下一步所生成的执行体中看出来。bss 和 data 数组的区别如下:
  • bss 数组 —— 此数组是未初始化的数据,保存在执行体的          .bss 段。此段不占用执行体的任何空间。
  • data 数组 —— 此数组是已初始化的数据(非零),必须保存在执行体本身的 .data 段。在上述情况下,每个双精度是 8 字节,所以要占用执行体中 8*1024*1024 (8MB) 字节的空间。
要查看执行体中的这些特性,只需编译此程序,然后用 readelf 命令显示段信息,如  所示。
清单 2. C 程序中的段信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# cc  sections.c  -o sections

# ls -l sections
-rwxr-xr-x 1 root root 8400154 2006-12-03 18:52 sections
   
# readelf -S sections   
There are 36 section headers, starting at offset 0x8012cc:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .interp           PROGBITS        10000154 000154 00000d 00   A  0   0  1
  [ 2] .note.ABI-tag     NOTE            10000164 000164 000020 00   A  0   0  4
...
  [12] .text             PROGBITS        100002f0 0002f0 0005b0 00  AX  0   0 16
  [13] .fini             PROGBITS        100008a0 0008a0 000038 00  AX  0   0  4
...
  [23] .plt              PROGBITS        10010a28 000a28 000008 00  WA  0   0  4
  [24] .data             PROGBITS        10010a30 000a30 800008 00  WA  0   0  8
  [25] .bss              NOBITS          10810a38 800a38 800008 00  WA  0   0  8
  [26] .comment          PROGBITS        00000000 800a38 0000d9 00      0   0  1
...




在  所示的输出中,观察如下内容:
  • 执行体的大小 —— 执行体的大小是          8400154,对于较小的程序来说,这明显有些过大。
  • .text —— 文本是编译器生成的可执行指令。对于大型程序而言,可引导 libhugetlbfs 将此段加载进 16MB 大内存页。在本例中,可执行文本的大小只有 5b0(hex) 字节,所以不应将其放至 16MB 大内存页。
  • .data —— 程序中的数据段的大小为 800008(hex) 字节 。这与所声明的 8MB data          数组是相符的。初始化的数据是执行体本身的一部分,而这会使执行体变得很大,认识到这一点十分重要。通过偏移量则可以很容易看出这一点。数据段从偏移量          000a30 开始,而下一个段则开始于偏移量          800a38。
  • .bss —— 程序中的 .bss 段的大小也为 800008(hex) 字节,但它并不占用执行体中的空间,.bss 段以及下一个段的开始偏移量不会更改,两个都是          800a38(hex)。
将 data 数组更改为 bss 数组为了演示编译器是如何处理数组初值的,可以将 data_array 的初值从 5.0 更改为 0.0,注意到它现在变成了执行体中的 .bss 段,如下所示:
1
2
3
4
5
...
#define ELEMENTS 1024*1024
static double  bss_array[ELEMENTS];
static double  data_array[ELEMENTS] = {0.0};  <----  zero'ing makes this a .bss array
...




如果将 data_array 初始化为零,编译器会将其视为 .bss 段。需要重新编译,结果如  所示。请看如下的 .data 段。
清单 3. 现在在 .bss 段中的 .data 段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# cc  sections.c  -o sections

# ls -l sections
-rwxr-xr-x 1 root root 11546 2006-12-03 18:54 sections

# readelf -S sections
There are 36 section headers, starting at offset 0x12cc:

Section Headers:
  [Nr] Name          Type       Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]               NULL       00000000 000000 000000 00      0   0  0
  [ 1] .interp       PROGBITS   10000154 000154 00000d 00   A  0   0  1
  [ 2] .note.ABI-tag NOTE       10000164 000164 000020 00   A  0   0  4
...
  [12] .text         PROGBITS   100002f0 0002f0 0005b0 00  AX  0   0 16
  [13] .fini         PROGBITS   100008a0 0008a0 000038 00  AX  0   0  4
...  
  [23] .plt          PROGBITS   10010a28 000a28 000008 00  WA  0   0  4
  [24] .data         PROGBITS   10010a30 000a30 000008 00  WA  0   0  4  \
                                        <----- No longer a data array
  [25] .bss          NOBITS     10010a38 000a38 1000008 00  WA  0   0  8 \
                                        <----- Now twice the size
  [26] .comment      PROGBITS   00000000 000a38 0000d9 00      0   0  1
...




注意 size 列以及与大小相关的偏移量。所发生的更改描述如下:
  • 执行体的大小 —— 执行体的大小现在只有 11546 字节。
  • .data —— 在 .data 段,大小从前例所示的 800008(hex) 降为只有 000008(hex)。data_array 现在被视为          .bss 段。
  • .bss —— 在 .bss 段,大小现在是前例所示的两倍,即 1000008(hex),为两个数组大小之和(           bss_array 的 800000(hex) 加上 data_array 的 800000(hex)),但它不会占用执行体中的任何 “空间”。下一个段的偏移量也不会更改。
对段的总结为获得较大数量的内存,大多数应用程序会使用未初始化的数据声明或者使用        malloc 命令。        libhugetlbfs 提供了两种简单的方法来将 .bss 段和由        malloc 命令分配的内存加载进系统大内存页。libhugetlbfs        也提供了将执行体的 .text 段和 .data 段加载进大内存页的方法,但不如 .bss 段和由 malloc 分配的内存那么常见。
返回列表