【问题标题】:Too many child with fork() [duplicate]使用 fork() 的孩子太多 [重复]
【发布时间】:2013-08-31 14:52:52
【问题描述】:

代码:

for ( ii = 0; ii < 24; ++ii) {

    switch (fork()) {

        case -1 : {
                printf("\n\nproblem with fork() !!! \n\n");
                exit(0);
                };

        case 0 : {
                WriteOnShared_Mem(ii);
                }break;
        default : {
                ChildPidTab[ii] = p;
                usleep(50000);
                ReadShared_MemMp(nbSect, 24,ChildPidTab);
                };
    }
}

我的问题是我得到了太多的孩子(nbenfant = 24),我得到了比 24 多得多的孩子:/

这是我今天在这里发的第 3 篇文章,但仍然没有解决 :(

谢谢

【问题讨论】:

  • 请在您的代码中使用英文(标识符、字符串、cmets)
  • 请不要重复发布相同的问题...

标签: c fork


【解决方案1】:

仔细阅读fork(2) 手册页。把那页读了好几遍,很难理解。另请阅读 fork (system call)processes (computing) 上的维基页面。

请理解 - 这需要时间 - fork 在成功时同时返回两次:一次在父项中,一次在子项中

fork 系统调用可能因多种原因而失败(然后返回 -1)。如果fork 失败,请使用perror 或其他方式显示errno。您应该始终保留fork 的结果。所以代码

for (ii = 0; ii < 24; ++ii) {
 fflush(NULL);
 pid_t p = fork();
 switch (p) {
    case -1 : // fork failed 
            printf("\n\nproblem with fork() in pid %d error %s!!! \n\n",
                   (int) getpid(), strerror(errno));
            exit(EXIT_FAILURE);
            break;
    case 0: // child process
            WriteOnShared_Mem(ii);
            ii = MAX_INT; // to stop the for loop
            break;
    default: // parent process
            ChildPidTab[ii] = p;
            /// etc.... some synchronization is needed
            break;
    }

特别是,fork 可能会失败,因为

   EAGAIN fork() cannot allocate sufficient memory to copy the
          parent's page tables and allocate a task structure for 
          the child.
   EAGAIN It was not possible to create a new process because the
          caller's RLIMIT_NPROC resource limit was encountered.  To
          exceed this limit, the process must have either the
          CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.
   ENOMEM fork() failed to allocate the necessary kernel structures
          because memory is tight.

如果您希望能够分叉更多进程,请尝试:

  • 使用setrlimit(2) 增加RLIMIT_NPROC 资源限制(可能由系统设施调用,因此还要查看/etc/pam.d/login

  • 降低fork-ing 程序所需的资源。特别是降低堆内存要求

  • 增加一些系统资源,比如交换。你可以swapon一些临时文件进行测试。

作为Joachim Pileborg replied,你应该避免分叉太多(分叉的进程继续循环,所以也再次分叉)。

不要忘记stdio 例程被缓冲。适当使用fflush(3)

我建议阅读Advanced Linux Programming 的书(可在线获得),其中有一整章解释了 Linux 上的进程处理。

顺便说一句,使用pstoppstree 检查您有多少进程(以及使用free 命令使用了多少内存,但在抱怨之前请阅读http://linuxatemyram.com/)。您的特定系统可能无法 fork 超过 24 次特定程序(因为缺乏资源)

还要研究简单 shell 的源代码(例如 sash)并使用 strace -f(例如在某些 shell 上或在您的程序上)来了解更多系统调用的作用。还学习如何使用gdb 调试器。

【讨论】:

  • 我只想要我 24 岁的孩子,但他们需要同时跑步。
  • “分叉太多”我是怎么分叉的 :(
  • 好的,感谢 fork() 错误的更正,但我无法检查它,因为我执行 fork() 时没有错误 -_-
  • 请花几个小时阅读教程和链接资源。你有一些基本的误解。你需要学习更多。并添加更多 printffflush 调用以进行调试。
  • 是的,先生,我知道,我仍然是一名学生,每天都在学习,但是当我没有得到任何东西时,我会来问像你这样的人:)
【解决方案2】:

这是因为每个孩子都继续循环,因此又分叉了自己的孩子。孩子们完成后,您应该从主函数返回或调用exit

【讨论】:

  • 是的,问题是我不能使用 exit() bcz 它会杀死孩子,我需要 24 个孩子同时运行:/ 那些 r 指令。
  • @shubha exit 调用只是退出当前进程,而不是它的父进程或兄弟进程。
  • 是的,如果我退出孩子,它会杀死他们,但我不希望我只想让 24 个孩子同时运行。这可能吗?
  • @shubha 你真的不能用多任务系统保证这一点。如果您调用的函数WriteOnShared_Mem) 在所有子进程创建之前返回,您希望发生什么?在继续使用该功能之前,您似乎需要进行一些同步以确保所有进程都在运行?
  • @shubha 好的,那么问题是当WriteOnShared_Mem 函数返回时,孩子们继续循环!函数返回后,您必须退出进程。
【解决方案3】:

子进程coutinue fork新的子进程,你只需要停止它。

像这样:

 switch (fork()) {

    case -1 : {
            printf("\n\nproblem with fork() !!! \n\n");
            exit(0);
            };

    case 0 : {
             i = 24 ;                 //--- here I set i = 24 , so child process will stop fork new child process.
            WriteOnShared_Mem(ii);
            }break;
    default : {
            ChildPidTab[ii] = p;
            usleep(50000);
            ReadShared_MemMp(nbSect, 24,ChildPidTab);
            };
    }
}

【讨论】:

  • 好吧,如果我真的像你说的那样,我将只有 1 个孩子?没有?
  • 否 你不明白fork 是如何工作的,或者你对普通的C编程太新手了。
  • 我是新手,我是去年才开始的:)
  • @shubha 你将有 24 个子进程同时运行\
猜你喜欢
  • 2018-08-10
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 2022-12-13
  • 1970-01-01
  • 2019-03-25
相关资源
最近更新 更多