内核宏的解释
Explanation of a macro in kernel
在内核2.4.37中,page.h中有这样一个宏:
struct page *mem_map;
struct page *page;
#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
我知道mem_map
是一个struct page
的数组,page
是一个struct
,那么page - mem_map
是什么意思呢?
嗯,我不确定,但也许指针地址比较?
我的意思是,如果其中之一是一个数组并且它没有被取消引用,那么我想操作将应用于地址。
编辑:(精度)
因此,在这种情况下,我认为此操作用于检查 "page" 是否在地址数组 "mem_map" 的范围内。
我们可以这样表示:Graphic representation
宏的实用性:
所以,"mem_map"是数组开始的地址,假设:0x0...5。
"mem_map"(max_mapnr)数组的大小为:5.
我们想知道"page"地址是否在"mem_map"数组的范围内。
真实案例:
假设"page"在"mem_map"中,2e元素。我们可以假设他的地址是这样的:0x0...7;
现在我们进行操作:((0x0...7 - 0x0...5) < 5)
。
我们得到 2。所以 "page" 地址在 mem_map.
错误案例:
否则如果"page"不在数组(0x0...D)中:我们的结果将是8。因此,8不小于"max_mapnr"(5)。所以这个页面不在"mem_map"数组中。
如果地址在数组地址 (0x0...2) 下方:
((0x0...2 - 0x0...2))
的结果将是一个负值。在那种情况下,他们无法与 "max_mapnr"(unsigned long) 进行比较。
我发现这个主题解释为什么比我好:
Signed/unsigned comparisons
所以对于简历:
你不能在 C 中的负值(有符号)和无符号值之间进行操作,因为他会自动转换它们。换句话说,当你做 (-3 - U_nbr)
时,如果你做 (((unsigned)-3) - U_nbr)
也是一样的。并且在选项中,如果您使用 gcc -Wall
标志编译,并且您不手动转换您的值,您将收到一条编译警告消息。
为了测试,我尝试 运行 此代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
unsigned long test = 0x0000F;
unsigned long test2 = 0x0000A;
unsigned long weird = 0x00002;
char* pt1 = "This is first test string !";
char* pt2 = "This is a test string";
printf("Try to make operation on two unsigned long result must be 5: %lu\n", (test - test2));
printf("Try to make operation between unsigned long result must be negative, so he will be cast: %lu\n", (weird - test2));
printf("Let's try the same with real adresses: %lu\n", (pt2 - pt1));
printf("And this is what happens with negative value: %lu\n", (pt1 - pt2));
printf("For be sure, this is the lenght of string 1. %lu\n", strlen(pt1));
return (0);
}
输出是:
Try to make operation on two unsigned long result must be 5: 5
Try to make operation between unsigned long result must be negative, so he will be cast: 18446744073709551608
Let's try the same with real adresses: 28
And this is what happens with negative value: 18446744073709551588
For be sure, this is the lenght of string 1. 27
因此,正如我们所见,负值被转换为 Unsigned long 而 return 是溢出的。如果您与 max_mapnr 进行比较,您会发现他是 "out of range"。
感谢 AnshuMan Gupta "weird case"。
它将计算mem_map数组中相应页面的索引,表示它在mem_map数组中的页数,假设为linux的pfn或页框编号(linux 假定 mem_map 数组从第 0 个 pfn 开始到最大 pfn),将 PHYS_PFN_OFFSET 添加到 pfn 将为您提供内存映射中的实际物理页框。
__page_to_pfn
max_mapnr是最大映射页数或最大页框数的限制。
set_max_mapnr
希望能解开你的疑惑。
在内核2.4.37中,page.h中有这样一个宏:
struct page *mem_map;
struct page *page;
#define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
我知道mem_map
是一个struct page
的数组,page
是一个struct
,那么page - mem_map
是什么意思呢?
嗯,我不确定,但也许指针地址比较?
我的意思是,如果其中之一是一个数组并且它没有被取消引用,那么我想操作将应用于地址。
编辑:(精度)
因此,在这种情况下,我认为此操作用于检查 "page" 是否在地址数组 "mem_map" 的范围内。
我们可以这样表示:Graphic representation
宏的实用性:
所以,"mem_map"是数组开始的地址,假设:0x0...5。 "mem_map"(max_mapnr)数组的大小为:5.
我们想知道"page"地址是否在"mem_map"数组的范围内。
真实案例:
假设"page"在"mem_map"中,2e元素。我们可以假设他的地址是这样的:0x0...7;
现在我们进行操作:((0x0...7 - 0x0...5) < 5)
。
我们得到 2。所以 "page" 地址在 mem_map.
错误案例:
否则如果"page"不在数组(0x0...D)中:我们的结果将是8。因此,8不小于"max_mapnr"(5)。所以这个页面不在"mem_map"数组中。
如果地址在数组地址 (0x0...2) 下方:
((0x0...2 - 0x0...2))
的结果将是一个负值。在那种情况下,他们无法与 "max_mapnr"(unsigned long) 进行比较。
我发现这个主题解释为什么比我好:
Signed/unsigned comparisons
所以对于简历:
你不能在 C 中的负值(有符号)和无符号值之间进行操作,因为他会自动转换它们。换句话说,当你做 (-3 - U_nbr)
时,如果你做 (((unsigned)-3) - U_nbr)
也是一样的。并且在选项中,如果您使用 gcc -Wall
标志编译,并且您不手动转换您的值,您将收到一条编译警告消息。
为了测试,我尝试 运行 此代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
unsigned long test = 0x0000F;
unsigned long test2 = 0x0000A;
unsigned long weird = 0x00002;
char* pt1 = "This is first test string !";
char* pt2 = "This is a test string";
printf("Try to make operation on two unsigned long result must be 5: %lu\n", (test - test2));
printf("Try to make operation between unsigned long result must be negative, so he will be cast: %lu\n", (weird - test2));
printf("Let's try the same with real adresses: %lu\n", (pt2 - pt1));
printf("And this is what happens with negative value: %lu\n", (pt1 - pt2));
printf("For be sure, this is the lenght of string 1. %lu\n", strlen(pt1));
return (0);
}
输出是:
Try to make operation on two unsigned long result must be 5: 5
Try to make operation between unsigned long result must be negative, so he will be cast: 18446744073709551608
Let's try the same with real adresses: 28
And this is what happens with negative value: 18446744073709551588
For be sure, this is the lenght of string 1. 27
因此,正如我们所见,负值被转换为 Unsigned long 而 return 是溢出的。如果您与 max_mapnr 进行比较,您会发现他是 "out of range"。
感谢 AnshuMan Gupta "weird case"。
它将计算mem_map数组中相应页面的索引,表示它在mem_map数组中的页数,假设为linux的pfn或页框编号(linux 假定 mem_map 数组从第 0 个 pfn 开始到最大 pfn),将 PHYS_PFN_OFFSET 添加到 pfn 将为您提供内存映射中的实际物理页框。 __page_to_pfn
max_mapnr是最大映射页数或最大页框数的限制。 set_max_mapnr
希望能解开你的疑惑。