我创建了一个共享库,其中我有静态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
答案 0 :(得分:1)
页面与页面大小对齐。因此,如果您的页面大小为4 kB,0xAABBC000 - 0xAABBCFFF
属于同一页面,0xAABBD000 - 0xAABBDFFF
等等。
因此,如果C
的地址为0xAABBCF00
且T0
的地址为0xAABBD000
,则其地址之间的差异小于4 kB,但它们仍然属于不同的页面。但是,极端可能性中的T0[0]
和T0[1]
属于同一页面。尝试运行objdump -h a.out
。
答案 1 :(得分:0)
加载整个缓存行的任何部分时都会加载。您似乎在描述一种情况,其中数据的开头与代码的一部分位于同一缓存行中。我很惊讶它会以这种方式链接/加载,但它应该很容易与调试器确认(或矛盾)。 缓存行大小和此行为的其他详细信息将因CPU型号而异。
查看C()的基址更容易,但信息量较少。重要的是获取的C()的最高指令的地址(不一定执行)。我希望它与数据的开头在同一个缓存行中。