Chinaunix首页 | 论坛 | 博客
  • 博客访问: 38511
  • 博文数量: 10
  • 博客积分: 360
  • 博客等级: 一等列兵
  • 技术积分: 100
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-31 10:24
文章分类
文章存档

2011年(1)

2010年(3)

2009年(6)

我的朋友

分类: LINUX

2009-10-10 10:25:07

遇到了嵌入式linux下面系统级内存泄露问题。跟踪问题日志。
平台:ARM9
内核:2.6.22

问题:execl造成系统内存减少,通过cat /proc/memoinfo 发现少的内存并且都移往slab中去了
测试代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

int main()
{
    int i = 0;
    int pid = 0;

    for (i=0; i<1000; i++)
    {
        pid = fork();
        if (pid < 0)
        {
            printf("fork() fail!\n");
            continue;
        }
        else if (pid == 0) //child
        {
            //system("ls");
            execl("/bin/ls", "ls", "", NULL);
            printf("execl() here!\n");
            exit(0);
        }
        else
        {
            waitpid(pid, 0, 0);
            printf("[%d] exited!", pid);
        }

        printf("%d\n", i);
       
    }

    return 0;
}

20091010:在PC上ubuntu 9.04上测试这个程序发现没有内存减少的现象。在ARM9上发现,每次执行1000次左右,导致有300k左右的内存减少。可能与内核版本(ubuntu 9.04是2.6.30的kernel版本)有关系,通过google或百度并没有发现有这样的问题。估计是配置内核导致的问题。下一步将通过cat /proc/slabinfo 来研究内存多出来的部分的来源。

20091011:通过1000此调用之后,通过cat /proc/slabinfo对比发现,变化最大的是
name            : tunables : slabdata
size-256             120    120    256   15    1 : tunables  120   60    0 : slabdata      8      8      0
size-256            1120   1125    256   15    1 : tunables  120   60    0 : slabdata     75     75      0
计算,pagesperslab为1,即一个page中有一个slab,(75-8)×4K = 268k左右。为了排除其他部分造成的内存泄露。做了一个测试,频繁的进行1000次malloc和free,发现size-256项也无特别变化。可以初步判断,应该是size-256块slab中出现了内存没有释放的行为。下一步动作,研究源代码do_execve部分来看分配192~256k的内存的嫌疑函数以及是否在退出后被释放。

20091012:为了排除slab本身有bug的情况,将内核分配机制改为slub,结果,依然在执行1000次之后少出300k的内存空间。在slub.c中,static struct kmem_cache *get_slab(size_t size, gfp_t flags)函数中插入log,这里是分配的必经之路。当分配的大小在128~256之间时,log出分配的size大小。执行测试程序,发现
_DEBUG: get slab size = 192
_DEBUG: get slab size = 208
就是说有分配192和208的需求在。
而简单的ls,或pwd都会打印这个出来,本人据此推断,分析进行shell命令也会有内存泄露问题。手动ls100次,果不其然,大概有52k的内存泄露,平均起来就是2个256的空间没有收回。
对log的出处一直跟踪(callstack),发现最终锁定在load_elf_binary这个函数中,仔细看了code,发现log不是很规范,与同事交流了,原来被touch过。立即找到kmalloc和kfree的地方,看哪个kfree有没有漏掉,果然发现漏洞。去对比2.6.22历史版本,发现同事的修改有个地方忘记free了,兴奋之余,赶紧改过来,测试5000次。结果正常。原来这个添加的code是同事用来调试用的,忘记砍掉了。我说呢,内核应该没有这样明显的错误的,google也无任何关于此的问题。经过此次跟踪后,对内核内存分配更加理解。
阅读(1712) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~