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

Fre*_*ddy 33 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等)?
  • 其他?

vet*_*tri 48

尝试使用该getconf实用程序,这将允许您轻松检索页面大小.

getconf PAGESIZE
Run Code Online (Sandbox Code Playgroud)

  • 我不认为这回答了OP的问题,但它是有用的信息,因为 sysconf(_SC_PAGESIZE) 似乎在 linuxia64 上返回 4K (而 mprotect 在未与 16K 边界对齐的页面上失败)。 (4认同)
  • 我的 x86-64 仅返回 4k,但它有 4k、2M 和 1G 页面。 (3认同)

Pav*_*ath 17

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

  • 我没有发现`Mapped/nr_mapped`甚至接近`getconf PAGESIZE`提供的内容 (2认同)

Jay*_*ayM 6

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

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


小智 6

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

例如:

cd /proc/1
grep -i pagesize smaps

KernelPageSize:        4 kB
MMUPageSize:           4 kB
Run Code Online (Sandbox Code Playgroud)


Fre*_*ddy 5

这就是我最终做的:

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

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

  • 菜鸟问题。您能详细解释一下使用 getconf API 的包装器吗?我的意思是您是否在 popen() 函数或其他函数中调用了 getconf 命令。如果再多一点光线,我们会非常感激。 (2认同)