非自愿的上下文切换:如何避免它们?

13


我有一个小应用程序正在运行,我想检查是否存在任何内存泄漏,因此我添加了以下代码:

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命令读取/proc/<进程ID>/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

然后我搜索并发现了一些东西,但对我来说太过技术化无法理解。

从中我得到的是,这是应用程序切换处理器或其他什么东西所导致的? (顺便说一句,我有一个Amd 6核处理器)。

如何防止我的应用程序这样做,并在运行应用程序时这可能造成多大问题?

提前谢谢,Robin。


1
既然您可能正在使用Linux,为什么不使用Valgrind来帮助您找到可能的内存泄漏呢? - Palmik
我不明白你为什么认为那段代码可以帮助你检测内存泄漏。 - Ferruccio
我猜这可能会帮助他找到分配/销毁输入文件流的代码中的内存泄漏问题。 - Sylvain Defresne
是的,文件处理器从可能的三个不同源(三个不同的虚拟文件系统)中读取文件。文本文件大约有1MB,我只是想检查是否所有这些都释放了内存。如果没有,使用量会迅速增加,对吧?无论如何,我用valgrind检查过了,没有泄漏被检测到,所以应该没问题 :) - Robin
针对此X Y,访问:https://dev59.com/rHE85IYBdhLWcg3w03Dz - Ciro Santilli OurBigBook.com
3个回答

21

自愿的上下文切换是指当你的应用程序在系统调用中被阻塞时,内核决定将其时间片切换到另一个进程。

非自愿的上下文切换是指当你的应用程序已经使用完调度程序分配给它的所有时间片时发生的(内核试图假装每个应用程序都拥有整个计算机,可以使用尽可能多的 CPU,但必须从一个进程切换到另一个进程,以便用户产生并行运行的幻觉)。

在您的情况下,由于您正在打开、关闭和从同一文件中读取内容,该文件很可能在整个进程执行过程中保留在虚拟文件系统缓存中,并且由于系统或库缓存原因,您的程序被内核抢占而不会被阻塞。另一方面,Firefox、Gdm 和 Netbeans 大多数情况下都在等待来自用户或网络的输入,并且不能被内核抢占。

这些上下文切换并不会造成伤害。相反,它们使你的处理器公平地为所有应用程序服务,即使其中一个应用程序正在等待某些资源。

顺便说一下,要检测内存泄漏,更好的解决方案是使用专门的工具,例如valgrind


3
比起Unix,几乎所有常用的操作系统都支持抢占式多任务处理(即预先中断正在执行的任务并分配给其他任务执行)。 - Sylvain Defresne
非自愿的?还是你的意思是自愿的?据我所知,当你调用操作系统时,你将控制权交给它,因此如果它决定切换上下文,那么这是“自愿的”。而当你的应用程序消耗大量CPU(例如在那些循环中),操作系统可能会选择强制暂停应用程序的执行并“非自愿地”切换上下文。我错了吗? - Sergei Tachenov
你说得对,我混淆了。我会编辑我的回答。谢谢。 - Sylvain Defresne
另外,据我所知,voluntary包括一个yield timeslice系统调用(类似于sched_yield())。 - Katastic Voyage

3

1
为了查找内存泄漏,最好安装并使用Valgrindhttp://www.valgrind.org/。它可以识别堆中的内存泄漏和内存错误条件(使用未初始化的内存,大量其他问题)。我几乎每天都会使用它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接