免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6038 | 回复: 11
打印 上一主题 下一主题

linux system调用问题 虔诚求助 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-05 16:33 |只看该作者 |倒序浏览
最近遇到一个问题,我的一个linux进程(非常大,占用机器70%的内存),在进程运行过程中,我想执行一个shell命令,起初是调用system("shell命令"),但是system会fork一个子进程来完成这个操作,但是这时内存已经不够用(不足以复制出新的子进程), 导致出错。

后来我做了一个测试例子,利用malloc+memset占用系统大部分内存,调用system,却可以成功,很奇怪,有可能我的测试例子不能模拟出我那个linux进程?

问题: system调用 会复制父进程的内容吗? 具体复制哪些呢? 为什么malloc的内存不会被复制(测试例子system成功,说明没有复制全部内容,负责剩余内存不够)
         (system函数里调用的是fork,然后执行的exec,fork不是写时复制吗? 没有写 怎么会复制内存了呢?)

       如果使用vfork是不是可以,vfork和父进程共享内存的吧 而没有单独复制内存。


不知道我有没有讲清楚,请大家多帮忙,任何回复都welcome的。

论坛徽章:
0
2 [报告]
发表于 2009-08-05 16:49 |只看该作者
fork是copy-on-write的,不会复制父进程的所有东西,只复制一小部分。vfork更不好。

论坛徽章:
0
3 [报告]
发表于 2009-08-05 16:53 |只看该作者
调用system到底会不会复制父进程的东西呢?  

我看到还有人自己写的my_system用vfork代替fork 号称这样不会复制没用的东西:


原文如下:


因为新fork出来的子进程会自动把父进程的数据段继承一份出来,如果父进程的数据段比较大的话,会占用较多的内存。建议自己做一个system函数,用vfork取代fork即可。

自己的system函数


int my_system(char* cmd)
{
    intstatus = 0;
    pid_t pid;

    if ((pid = vfork()) <0)
    {
        printf("vfork process error! \n");
        status = -1;
    }
    else if (pid==0)
    {
        const char *new_argv[4];
        struct sigaction sa_cld;
        sa_cld.sa_handler = SIG_DFL;
        sa_cld.sa_flags = 0;

        /* 在子进程中放开SIGINT信号 */
        sigemptyset(&sa_cld.sa_mask);
        sigaction (SIGINT, &sa_cld, NULL);
        sigaction (SIGQUIT, &sa_cld, NULL);
      
        new_argv[0] = SHELL_NAME;
        new_argv[1] = "-c";
        new_argv[2] = cmd;
        new_argv[3] = NULL;

        if (execve(SHELL_PATH,(char *const *) new_argv, environ) <0)
        {
            printf("fail to execve %s! errno: %d\n",cmd,errno);
            exit(1);
        }
        else
        {
            exit(0);
        }
    }
    else
    {
            waitpid(pid,&status,0);
    }

    return status;
}

论坛徽章:
0
4 [报告]
发表于 2009-08-05 17:04 |只看该作者
LZ自己不是都知道fork是写时复制的么~ 不会复制那么多数据的

我觉得LZ的问题不是fork or vfork的问题,如果怀疑改改代码试试看就好了。

我想,LZ调用system函数的那个进程可能有蹊跷,换用popen、或者自己写个vfork版的system试试看吧~ 或者直接fork一下,然后子进程打印个什么东西就退出……

一般这种问题不是靠想和讨论就能解决的,多做试验才有前途

论坛徽章:
0
5 [报告]
发表于 2009-08-07 08:27 |只看该作者
system调用 fork + execv,没有拷贝父进程什么东西吧

论坛徽章:
0
6 [报告]
发表于 2012-04-28 22:46 |只看该作者
本帖最后由 zxc381219 于 2012-04-28 22:46 编辑

啊!这么多年了!  我自己回复下这个问题吧

1) system 调用fork创建子进程
2) fork复制父进程的数据段,需要申请分配内存的
3) fork申请分配内存时会根据一个系统的配置文件 /proc/sys/vm/overcommit_memory ,判断是否满足分配内存的条件,我前面的问题中提到了,版本进程占用了系统大部分的内存,当该进程中的某块数据区大小大于剩余全部系统的剩余内存时(别怀疑,我们的服务器就是有这种情况,2G内存,主进程占用了1.7G 其中一块连续的数据大于了300M ) ,加之,当时的配置文件overcommit_memory 写入的是0,即:检查是否有足够的可用内存供应用进程使用。导致了system返回失败,分配内存失败。

PS: 该配置文件的解释:
/proc/sys/vm/overcommit_memory
该文件指定了内核针对内存分配的策略,其值可以是0、1、2。
0, 表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
1, 表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
2, 表示内核允许分配超过所有物理内存和交换空间总和的内存

论坛徽章:
1
拜羊年徽章
日期:2015-03-03 16:15:43
7 [报告]
发表于 2012-04-30 07:56 |只看该作者
本帖最后由 linuxfellow 于 2012-04-30 08:52 编辑

回复 6# zxc381219
多谢楼主时隔多年还来分享问题解决经验。
就是说你的系统里, 子进程实际上用不了剩下的内存, 只要把/proc/sys/vm/overcommit_memory改成1,或2, 就没问题
有点奇怪,为何有父进程的data section超过剩下的内存就不能fork子进程了?

论坛徽章:
0
8 [报告]
发表于 2012-04-30 23:35 |只看该作者
本帖最后由 zxc381219 于 2012-04-30 23:38 编辑

回复 7# linuxfellow

可以看一下fork.c的源码,fork复制子进程时会复制几个项:
  1.         /* copy all the process information */
  2.         retval = copy_semundo(clone_flags, p);
  3.         if (retval)
  4.                 goto bad_fork_cleanup_audit;
  5.         retval = copy_files(clone_flags, p);
  6.         if (retval)
  7.                 goto bad_fork_cleanup_semundo;
  8.         retval = copy_fs(clone_flags, p);
  9.         if (retval)
  10.                 goto bad_fork_cleanup_files;
  11.         retval = copy_sighand(clone_flags, p);
  12.         if (retval)
  13.                 goto bad_fork_cleanup_fs;
  14.         retval = copy_signal(clone_flags, p);
  15.         if (retval)
  16.                 goto bad_fork_cleanup_sighand;
  17.         retval = copy_mm(clone_flags, p);
  18.         if (retval)
  19.                 goto bad_fork_cleanup_signal;
  20.         retval = copy_namespaces(clone_flags, p);
复制代码
如果这个配置文件里面被置为1    就不会执行判断内存是否不够(需要的大于剩余的) 而是直接分配内存。

论坛徽章:
0
9 [报告]
发表于 2012-04-30 23:53 |只看该作者

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

  20.         vm_acct_memory(pages);

  21.         /*
  22.          * Sometimes we want to use more memory than we have
  23.          */
  24.         if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
  25.                 return 0;
复制代码

论坛徽章:
0
10 [报告]
发表于 2012-04-30 23:57 |只看该作者
==============================================================

overcommit_memory:

This value contains a flag that enables memory overcommitment.

When this flag is 0, the kernel attempts to estimate the amount
of free memory left when userspace requests more memory.

When this flag is 1, the kernel pretends there is always enough
memory until it actually runs out.

When this flag is 2, the kernel uses a "never overcommit"
policy that attempts to prevent any overcommit of memory.

This feature can be very useful because there are a lot of
programs that malloc() huge amounts of memory "just-in-case"
and don't use much of it.

The default value is 0.

See Documentation/vm/overcommit-accounting and
security/commoncap.c::cap_vm_enough_memory() for more information.

=============================================================
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP