繁体   English   中英

C中的“代码”部分与“ DATA”部分一起加载了多少内存

[英]How much DATA section memory is loaded along with Code section in C

我创建了一个共享库,其中有4个函数的静态const数据部分和代码部分。

这是我的静态const数据部分的详细信息,

static const u32 T0[256] = { 256 NON_ZERO value };
static const u32 T1[256] = {256  NON_ZERO value };
static const u32 T2[256] = {256  NON_ZERO value };
static const u32 T3[256] = {256  NON_ZERO value };
static const u32 T4[256] = {256  NON_ZERO value };
static const u32 T5[256] = {256  NON_ZERO value };
static const u32 T6[256] = {256  NON_ZERO value };
static const u32 T7[256] = {256  NON_ZERO value };
static const u32 T8[256] = {256  NON_ZERO value };
static const u32 T9[10] = {10 NON_ZERO value };

静态const部分正下方定义的不同函数

int A();
int B();

// Access different index of T0 - T3 table 
void C();

void D();

根据我的理解,text / code部分将包含可执行指令,而data部分将包含初始化的静态数据(为简单起见,我都是静态const)

在C()函数内部,以随机顺序访问T0,T1,T2和T3的不同索引。

故意在C()中,我尚未访问T0 [0]。

但是,每次我调用C()函数时,无论是否在C()函数内部访问T0 [0],它都会加载T0 [0]。

我的问题是数据段和代码段一起加载了多少相邻内存?

我当时想可能是整个4KB页面都已加载,因此每次调用C()函数时,整个4KB页面都已加载,因此T0 [0]也随之加载。

但是,实验结果表明此概念并非正确/正确。

让我详细解释如下。

我已经计算出函数C()与不同静态const数据之间的距离,如下所示

Base address of C - Base address of T0[0] = 3221 Bytes
Base address of C - Base address of T1[0] = 4345 Bytes
Base address of C - Base address of T2[0] = 5369 Bytes
Base address of C - Base address of T3[0] = 6393 Bytes

因此,每当调用C()时,仅加载64Bytes(即T0 [0])。 T0 [1],T0 [2],... T0数组的一部分也与C()属于同一4KB页面未加载(如果整个4KB页面都已加载,则必须加载它们,但是实验结果表明它们未加载)。 因此我的整个4KB页面存储器的概念加载是错误的。

编辑1:基于@nemetroid的注释,C()和T0 [0]可能属于不同的页面。 这就是为什么我在这里添加C()和T0 [0]的基址。

Base address of T0[0]=0xB7758D40 ,
Base address of C=0xB7758047 when T0[0] is loaded.

在其他实验中,当我在静态const u32 T0 [256] = {.....}之前添加另一个64Byte的静态const(例如static const int DATA = 10;)时,

这些距离变成

Base address of C - Base address of T0[0] =3385 Bytes [ =64 + Base address of C - Base address of T0[0]]
Base address of C - Base address of T1[0] = 4345+64 Bytes =4409 Bytes [=64 + Base address of C - Base address of T0[0]+1024]
Base address of C - Base address of T2[0] = 5369+64 Bytes = 5433 Bytes[=64 + Base address of C - Base address of T0[0]+2*1024]
Base address of C - Base address of T3[0] = 6393 +64 Bytes = 6457 Bytes[=64 + Base address of C - Base address of T0[0]+3*1024]

编辑1:

Base address of T0[0]=0xB775cD80 (just shifted by 64Bytes),
Base address of C=0xB775C047 ( in this case T0[0] is not loaded)

现在,尽管T0 [0]仍与C()一起存在于同一4KB页面中(仅移位64个字节),但是只要调用C()都不会加载它。 因此,在这里我不能再说C(),整个4KB页面都已加载。

您能帮助我解释/理解为什么在C()调用时总是访问/加载T0 [0]的原因,尽管C()内部没有访问/使用T0 [0]吗?

或任何链接以了解程序的内存布局以及在程序执行期间加载的内存大小。

我正在使用Debian OS和gcc编译器。

注意:要计算是否加载了T0 [0],在调用C()之前,我只是使用clflush()指令刷新了T0 [0],然后在调用C()之后,我使用rdtsc()计算了访问时间。

编辑1:我正在使用Intel Core i3机器。

Size of L1=32KB, 8 way associative, cache line size=64bytes
Size of L2=256KB, 8 way associative, cache line size=64bytes
Size of L3=3MB, 12 way associative, cache line size=64bytes

页面与页面大小对齐。 因此,如果页面大小为4 kB, 0xAABBC000 - 0xAABBCFFF属于同一页面, 0xAABBC000 - 0xAABBCFFF属于同一页面, 0xAABBD000 - 0xAABBDFFF

因此,如果C地址为0xAABBCF00T0地址为0xAABBD000则它们之间的地址差小于4 kB,但它们仍属于不同的页面。 然而,极有可能的T0[0]T0[1]属于同一页面。 尝试运行objdump -h a.out

整个高速缓存行的任何部分加载时都会加载。 您似乎正在描述一种情况,其中数据的开头与代码的一部分位于同一缓存行中。 我很惊讶它会以这种方式链接/加载,但是应该很容易与调试器确认(或矛盾)。 缓存行大小和此行为的其他详细信息将因CPU型号而异。

查看C()的基址比较容易,但信息量较少。 重要的是所获取的C()的最高指令的地址(不一定执行)。 我希望它与数据开始处在同一缓存行中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM