Linux内存管理和优化

我在做嵌入式项目的时候发现了一个问题:当使用内存比较大时,调用系统函数system或者popen打开新进程时,系统会提示错误,errno=12,表示内存不够。于是做了一些分析。

我的硬件的总内存为128M,系统启动后,加载文件系统后还剩余大约110M的空间。当我的程序运行后,大约还剩余2M左右的内存(通过free或者top查看)

这个程序malloc了一个60M,另外还有一些malloc,但不会超过10M。不过它是基于QTSDK写的,所以在调用sdk时候可能也会申请一些内存。但不管如何,最后剩余2M的时候,system或者popen就会失败。(尽管只是一些cp和rm命令)


于是我就想查查到底为什么。

对于sytem(先不说popen)函数调用,它能够执行shell命令,我查到的system实现如下:

 int system(const char *cmd)
 {
  pid_t pid;
  int status;
  if(cmd == NULL)
  {
  return 1;
  }
  if((pid = fork()) < 0)
  {
  status = -1;
  }
  else if(pid == 0)
  {
  execl("/bin/sh", "sh", "-c",cmd, (char*)0);
  _exit(127);
  }
  else
  {
  while(waitpid(pid, &status, 0) < 0)
  {
  if(errno != EINTR)
  {
  status = -1;
  break;
  }
  }
  }
  return status;
 } 

可以看到fork函数,fork函数执行时会拷贝父进程的数据段和代码段,不过它使用了写时拷贝技术,为了减少内存的使用。说到fork还有一个vfork,它会共享父进程的数据段(代码段内?),因此占用内存会更少。(当然还有其他区别,例如子进程会先运行,结束后才运行父进程)


fork函数什么情况下会失败,并且原因是缺少内存呢?

有个链接提供了线索:http://bbs.chinaunix.net/thread-1965115-1-1.html

帖子了说了,fork的实现中需要检查内存是否够用,只要父进程某块连续数据区大于现系统可用物理内存时会报错。如下:

        /* copy all the process information */
        retval = copy_semundo(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_audit;
        retval = copy_files(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_semundo;
        retval = copy_fs(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_files;
        retval = copy_sighand(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_fs;
        retval = copy_signal(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_sighand;
        retval = copy_mm(clone_flags, p);
        if (retval)
                goto bad_fork_cleanup_signal;
        retval = copy_namespaces(clone_flags, p);

不过可以通过/proc/sys/vm/overcommit_memory调整检查策略:

/*
 * Check that a process has enough memory to allocate a new virtual
 * mapping. 0 means there is enough memory for the allocation to
 * succeed and -ENOMEM implies there is not.
 *
 * We currently support three overcommit policies, which are set via the
 * vm.overcommit_memory sysctl.  See Documentation/vm/overcommit-accounting
 *
 * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
 * Additional code 2002 Jul 20 by Robert Love.
 *
 * cap_sys_admin is 1 if the process has admin privileges, 0 otherwise.
 *
 * Note this is a helper function intended to be used by LSMs which
 * wish to use this logic.
 */
int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
{
        unsigned long free, allowed;


        vm_acct_memory(pages);


        /*
         * Sometimes we want to use more memory than we have
         */
        if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS) 
                return 0;


因此,当我将/proc/sys/vm/overcommit_memory写入1时,system调用就没有报错了。


还是有点不安呐。又查了一些资料,

关于/proc/meminfo的

http://blog.sina.com.cn/s/blog_7106477c0100qj9d.html

让我看到了Cache的占用了稍多的内存


http://www.it165.net/os/html/201403/7603.html

让我知道Active和InActive代表最近使用过的内存和没有使用过的内存


http://www.newsmth.net/nForum/#!article/KernelTech/46857

让我知道Cache缓存的文件内容,Buffered缓存的是文件系统相关的Meta数据(文件节点?文件夹节点?)


http://www.linuxidc.com/Linux/2007-08/6995p2.htm

让我知道/proc/sys/vm/还有其他相关设置可以进行优化。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值