【问题标题】:Non voluntary context switches: How can I prevent them?非自愿上下文切换:如何防止它们?
【发布时间】:2010-12-13 15:44:47
【问题描述】:


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

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");
    }
}

当我运行应用程序时,我发现了 /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. 火狐:大约 200 个
  2. Gdm:2
  3. Netbeans:19

然后我用谷歌搜索并找到了一些东西,但对于我来说这是技术性的。 我从中得到的是,当应用程序切换处理器或其他东西时会发生这种情况? (顺便说一句,我有一个 Amd 6 核处理器)。

我怎样才能阻止我的应用程序这样做?在运行应用程序时,这会成为一个问题吗?

提前致谢, 罗宾。

【问题讨论】:

  • 既然你可能在linux上,为什么不使用valgrind来帮助你发现可能的内存泄漏?
  • 我不明白您为什么认为该代码可以帮助您检查内存泄漏。
  • 好吧,我想这可以帮助他找到分配/销毁那些输入文件流的代码中的内存泄漏。
  • 是的,文件处理程序从三个不同的源(三个不同的 vfs)中读取文件。文本文件大约 1 Mb,我只是想检查是否所有这些都释放了内存。如果没有,使用量会迅速增加,不是吗?无论如何,我检查了 valgrind 并没有检测到泄漏,所以我应该清楚:)

标签: c++ linux memory-management


【解决方案1】:

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

当您的应用程序使用了调度程序赋予它的所有时间片时,就会发生非自愿上下文切换(内核试图假装每个应用程序都拥有整台计算机,并且可以使用他们想要的尽可能多的 CPU,但必须从一个切换到另一个,让用户产生他们都在并行运行的错觉。

在你的情况下,由于你打开、关闭和读取同一个文件,它可能在整个进程执行期间停留在虚拟文件系统缓存中,并且你的程序正被内核抢占不阻塞(由于系统或库缓存)。另一方面,Firefox、Gdm 和 Netbeans 大多是在等待来自用户或来自网络的输入,不能被内核抢占。

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

顺便说一句,为了检测内存泄漏,更好的解决方案是使用专用于此的工具,例如 valgrind

【讨论】:

  • 比 Unix,每一个抢占式多任务操作系统(即几乎每一个常用的操作系统)。
  • 非自愿?还是你的意思是自愿的?据我了解,当您调用操作系统时,您将控制权交给它,所以如果它决定切换上下文,它是“自愿的”。而且当您的应用程序仅消耗大量 CPU 时(例如在那些循环中),操作系统可能会选择强制暂停应用程序的执行并“非自愿”切换上下文。我错了吗?
  • 你说得对,我也混了。我会编辑我的答案。谢谢。
  • 非常感谢您的回答和解释:)
  • 另外,AFAIK,自愿包括一个产量时间片系统调用。 (ala sched_yield())
【解决方案2】:

要添加到@Sylvain 的信息,这里有一篇很好的关于 Linux 调度的背景文章:"Inside the Linux scheduler" (developerWorks, June 2006)

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2013-06-20
      • 2014-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-04
      • 1970-01-01
      相关资源
      最近更新 更多