加载了多少数据部分内存以及C

时间:2015-08-05 10:36:39

标签: c++ c linux static

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

以下是我的静态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();

根据我的理解,文本/代码部分将包含可执行文件 指令,而数据部分将包含初始化的静态数据(为简单起见,所有都是静态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数组的一部分 属于同一个4KB页面,C()NOT LOADED(如果加载了整个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.

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

这些距离成为

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]

EDIT1:

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()?

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

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

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

编辑1: 我使用的是英特尔酷睿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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

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

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