非自愿的上下文切换:我该如何预防?

时间:2010-12-13 15:44:48

标签: c++ linux memory-management


我有一个小应用程序,我现在正在运行,我想检查是否有任何内存泄漏,所以我把这段代码:

for (unsigned int i = 0; i<10000; i++) {
    for (unsigned int j = 0; j<10000; j++) {
        std::ifstream &a = s->fhandle->open("test");
        char temp[30];
        a.getline(temp, 30);
        s->fhandle->close("test");
    }
}

当我运行应用程序时,我cat'ed / proc // status以查看内存是否增加。 运行约2分钟后输出如下:

Name:   origin-test
State:  R (running)
Tgid:   7267
Pid:    7267
PPid:   6619
TracerPid:  0
Uid:    1000    1000    1000    1000
Gid:    1000    1000    1000    1000
FDSize: 256
Groups: 4 20 24 46 110 111 119 122 1000 
VmPeak:   183848 kB
VmSize:   118308 kB
VmLck:         0 kB
VmHWM:      5116 kB
VmRSS:      5116 kB
VmData:     9560 kB
VmStk:       136 kB
VmExe:        28 kB
VmLib:     11496 kB
VmPTE:       240 kB
VmSwap:        0 kB
Threads:    2
SigQ:   0/16382
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000002004
SigCgt: 00000001800044c2
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: ffffffffffffffff
Cpus_allowed:   3f
Cpus_allowed_list:  0-5
Mems_allowed:   00000000,00000001
Mems_allowed_list:  0
voluntary_ctxt_switches:    120
nonvoluntary_ctxt_switches: 26475

除了最后一个值之外,没有一个值发生了变化,那么意味着没有内存泄漏吗?

但更重要的是,我想知道的是,如果最后一个值快速增加(在大约2分钟内大约26475个开关!),那就太糟糕了。

我查看了一些其他应用程序,以比较它们拥有多少非志愿开关:

  1. Firefox:约200
  2. Gdm:2
  3. Netbeans:19
  4. 然后我用Google搜索并发现了一些东西,但这是技术性的让我理解。 我从中获得的是,当应用程序切换处理器或其他什么时会发生这种情况? (我有一个Amd 6核处理器顺便说一句。)

    如何阻止我的应用程序执行此操作以及在运行应用程序时这可能会出现多大问题?

    提前致谢, 罗宾。

3 个答案:

答案 0 :(得分:20)

当您的应用程序在系统调用中被阻止并且内核决定将其时间片提供给另一个进程时,会发生自愿上下文切换。

当您的应用程序使用了调度程序归属于它的所有时间片时,会发生非自愿上下文切换(内核尝试假装每个应用程序都有自己的整个计算机,并且可以使用他们想要的尽可能多的CPU,但必须从一个切换到另一个,这样用户就会觉得它们都是并行运行的。)

在您的情况下,由于您正在打开,关闭和读取同一个文件,因此它可能会在整个过程执行过程中保留在虚拟文件系统缓存中,并且您的程序正被内核抢占,因为它是不阻塞(因为系统或库缓存)。另一方面,Firefox,Gdm和Netbeans主要等待来自用户或来自网络的输入,并且不得被内核抢占。

这些上下文切换无害。相反,它允许你的处理器被所有应用程序公平地使用,即使其中一个正在等待某些资源.≈

而且,为了检测内存泄漏,更好的解决方案是使用专用的工具,例如valgrind

答案 1 :(得分:3)

要添加@Sylvain的信息,有一篇关于Linux日程安排的背景文章:"Inside the Linux scheduler" (developerWorks, June 2006)

答案 2 :(得分:1)

要查找内存泄漏,安装和使用valgrind http://www.valgrind.org/要好得多。它将识别堆中的内存泄漏和内存错误情况(使用未初始化的内存,大量其他问题)。我几乎每天都在使用它。