我正在编写程序来计算 linux 系统中页面错误的时间。更准确地说,时间内核执行函数__do_page_fault
。
不知何故,我写了两个全局变量,分别命名为pfcount_at_beg
和pfcount_at_end
,当函数__do_page_fault
在函数的不同位置执行时,它们会增加一次。
为了说明,修改后的函数如下:
unsigned long pfcount_at_beg = 0;
unsigned long pfcount_at_end = 0;
static void __kprobes
__do_page_fault(...)
{
struct vm_area_sruct *vma;
... // VARIABLES DEFINITION
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
pfcount_at_beg++; // I add THIS
...
...
// ORIGINAL CODE OF THE FUNCTION
...
pfcount_at_end++; // I add THIS
}
我预计 pfcount_at_end 的值小于 pfcount_at_beg 的值。
因为,我认为,每次内核执行代码pfcount_at_end++
的指令时,它必须执行pfcount_at_beg++
(每个函数都从代码的最开头开始)。
另一方面,由于这两行代码之间有很多条件return
。
然而,结果恰恰相反。 pfcount_at_end
的值大于pfcount_at_beg
的值。
我使用 printk
通过自定义的 syscall
打印这些内核变量。我编写了用户级程序来调用系统调用
。
这是我的简单系统调用
和用户级程序:
// syscall
asmlinkage int sys_mysyscall(void)
{
printk( KERN_INFO "total pf_at_beg%lu\ntotal pf_at_end%lu\n", pfcount_at_beg, pfcount_at_end)
return 0;
}
// user-level program
#include<linux/unistd.h>
#include<sys/syscall.h>
#define __NR_mysyscall 223
int main()
{
syscall(__NR_mysyscall);
return 0;
}
有没有人知道这期间到底发生了什么?
刚才我修改了代码,使pfcount_at_beg
和pfcount_at_end
static
。然而结果并没有改变,即pfcount_at_end
的值大于pfcount_at_beg
的值。
所以可能它可能是由增量的原子操作引起的。如果我使用读写锁会更好吗?
最佳答案
++
运算符不保证是原子的,因此您的计数器可能会受到并发访问并具有不正确的值。你应该保护你的增量作为关键部分,或者使用 atomic_t
<asm/atomic.h>
中定义的类型, 及其相关 atomic_set()
和 atomic_add()
功能(以及更多)。
与您的问题没有直接关系,但使用特定的系统调用有点矫枉过正(但这也许是一种练习)。一个较轻的解决方案可能是使用 /proc
输入(也是一个有趣的练习)。
关于linux - 在 linux 中计算页面错误的结果令人困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27642340/