奇怪的 return 类型 __get_free_pages

Strange return type of __get_free_pages

为什么它 return unsigned long?为什么不是 void* 或 char*?

unsigned long __get_free_pages(unsigned int gfp_mask, unsigned int order)

我猜它 return 是一个地址,还是我完全误解了那个函数?

你更正了,它returns分配了第一页的第一个字节的内存地址。有趣的是 __get_free_pages() 内部使用的 page_address() 实际上 returns void*.

可以在 LDD3, chapter 11 (PDF) 中找到这样做的原因:

Although you must be careful when mixing different data types, sometimes there are good reasons to do so. One such situation is for memory addresses, which are special as far as the kernel is concerned. Although, conceptually, addresses are pointers, memory administration is often better accomplished by using an unsigned integer type; the kernel treats physical memory like a huge array, and a memory address is just an index into the array. Furthermore, a pointer is easily dereferenced; when dealing directly with memory addresses, you almost never want to dereference them in this manner. Using an integer type prevents this dereferencing, thus avoiding bugs. Therefore, generic memory addresses in the kernel are usually unsigned long, exploiting the fact that pointers and long integers are always the same size, at least on all the platforms currently supported by Linux.

"From the memory-management point of view, the system's RAM can be seen as a linear array of pages, so it can make a certain amount of sense to think of addresses as integer types — indexes into the array, essentially. Integers can also be used for arbitrary arithmetic; pointers in C can be used that way too, but one quickly gets into "未定义行为”领域,过度热情的编译器可能觉得有权制造各种混乱。因此 unsigned long 被确定为 return 类型 get_free_page()并且,一般来说,作为一个人指代可能出现在内存中任何地方的地址的方式。” -- 来自 https://lwn.net/Articles/669015/ -- 请阅读这个关于 unsigned long 与 void * :-)

的有趣故事