如何以编程方式获取Linux内核页面大小

时间:2011-02-03 15:28:06

标签: memory-management linux-device-driver dma

我正在为IA64开发Linux模块。我目前的问题是驱动程序使用PAGE_SIZE和PAGE_SHIFT宏进行dma页面分配。我遇到的问题是编译驱动程序的机器不是需要运行驱动程序的机器。因此,如果编译机器上的PAGE_SIZE为2 ^ 14K且目标机器为2 ^ 16K,则驱动程序将失败。

我不想将这个问题变成关于在不运行模块的机器上编译模块的“最佳实践”问题。我理解这个问题。我发现人们大多使用getpagesize()或sysconf(_SC_PAGE_SIZE)。这两个选项不在ia64内核头文件中,因此我无法使用它们。有没有其他方法可以获得运行时PAGE_SIZE?

我正在看的选项:

  • 在/ proc?
  • 中读取一些文件
  • 系统调用?
  • 让我通过推理计算PAGE_SIZE的其他函数(例如ORDER,getpageshift等)?
  • 其他?

7 个答案:

答案 0 :(得分:47)

尝试使用getconf实用程序,这样您就可以轻松检索页面大小。

getconf PAGESIZE

答案 1 :(得分:17)

一种近似方法是阅读/proc/meminfo并检查Mapped大小(截至目前我的52544 kB),然后检查nr_mapped中的/proc/vmstat(我的131136截至目前)。最后PAGE_SIZE = Mapped/nr_mapped。有时候这会给你一个准确的值(就像我引用的当前例子中的那样),有时它的近似但非常接近。 希望这有帮助!

答案 2 :(得分:6)

如果您正在尝试构建内核模块,则至少需要具有为模块运行的内核配置的内核头。这些将定义您需要的页面大小宏。如果您没有正确配置的标头,内核将拒绝加载您的模块。

在一台机器上编译模块以在另一台机器上运行没有任何问题,即使它是一个不同的架构。您只需要构建正确的内核源代码。

答案 3 :(得分:5)

这就是我最终做的事情:

  • 重新处理我当前的模块以获取一个名为page_shift的新模块参数,并用它来计算PAGE_SIZE (PAGE_SIZE = 1 << PAGE_SHIFT)
  • 创建了一个模块加载器包装器,它使用libc中的PAGE_SHIFT API获取当前系统getconf。此包装器获取当前系统页面的移位并将其作为模块参数传递。

现在,模块正在使用不同的PAGE_SIZE加载到不同的体系结构上而没有任何问题。

答案 4 :(得分:4)

查找页面大小的一种方法是从一个进程的smaps中获取它。

例如:

cd /proc/1
grep -i pagesize smaps

KernelPageSize:        4 kB
MMUPageSize:           4 kB

答案 5 :(得分:0)

我担心这是不可能的,因为页面大小被定义为内核的一部分。 如果还有用于编译内核模块的工具链,则需要页面大小知识。

至少对于当前的内核架构,不可能这样做。

答案 6 :(得分:0)

你可以运行一个测试,只需mmap一个具有不同偏移量的文件,看看哪个失败了。可能在内核模块中很烦人,但也许还有其他一些你可以使用的测试。