【问题标题】:fork() failing repeatedlyfork() 反复失败
【发布时间】:2019-08-07 15:25:06
【问题描述】:

我试图使用fork 创建一个子进程,但它反复返回-1,我试图找到原因并得出以下结论:

Fork() will fail and no child process will be created if:
[EAGAIN]           The system-imposed limit on the total number of pro-
                   cesses under execution would be exceeded.  This limit
                   is configuration-dependent.

[EAGAIN]           The system-imposed limit MAXUPRC (<sys/param.h>) on the
                   total number of processes under execution by a single
                   user would be exceeded.

[ENOMEM]           There is insufficient swap space for the new process. 

现在我不知道如何检查第一点和第三点,但查看点 MAXUPRC - 我查看了 sys/param.h

//<sys/param.h>
#define MAXUPRC     CHILD_MAX   /* max simultaneous processes */

CHILD_MAX 已在此处提及(unistd.h):

//<unistd.h> - DEFINED IN MY SYSTEM
#define _SC_CHILD_MAX            2 

CHILD_MAX - _SC_CHILD_MAX 每个用户 ID 的最大并发进程数。 不得小于 _POSIX_CHILD_MAX (25)。

现在我无法确定是否保持 _SC_CHILD_MAX 小于 25 是原因还是我必须调查第一个和第三个原因(它们很难检查为该系统是 Z/OS 访问受限,我对此不太了解)。

perror(""); 没有打印任何内容,errno 正在打印 655360。

  #include<stdio.h>
  #include<errno.h>
  #include<unistd.h>
  #include<stdlib.h>

   int main()
   {
       long int prc_id;

       prc_id=fork();

       if(prc_id ==0)
          calling_child();        
       else if(prc_id <0)
       {
           printf("errno - %d\n",errno); 
           printf("failed %d\n",prc_id);
           exit(0);
       }

      return 0;
 }

上面的代码运行良好,并在我自己的笔记本电脑(centos)上创建了一个子进程,但在开发环境中我想有一些限制。

calling_child 永远不会被调用,因为返回的 prc_id 是 -1(在进入函数时甚至不会打印第一条打印语句)。

【问题讨论】:

  • 其他几点可能对您有所帮助。首先,所有 errno/errno2 值都在名为“z/OS UNIX 系统服务:消息和代码”的书中定义。如果您在遇到问题后立即使用“printf("Error %x/%x - %s", errno, __errno2(), strerror(errno))" 或类似的东西(请记住,许多库函数重置 errno,因此您需要在发生错误时立即引用它)。此外,由于我向您推荐的文档以十六进制列出了 errno,因此通常最好使用“%x”打印它们。
  • 进程限制是并发运行的进程,而不是累积值。 “ps”命令告诉您正在运行什么,我从未见过配置少于 25 个进程/用户的 z/OS 系统。该设置来自 UNIX 服务配置文件 - 类似于 SYS1.PARMLIB(BPXPRM00)。其中,MAXPROCSYS(系统范围的进程限制)和 MAXPROCUSER(每个用户的最大进程数)是关键。如果需要,也可以逐个用户覆盖这些值。如果您有权访问 z/OS 操作员控制台,“D OMVS,LIMITS”命令将告诉您当前设置。

标签: c fork zos


【解决方案1】:

我将您的示例程序复制到我的运行 z/OS 版本 2.3 的 z/OS 系统中,由于您省略了 calling_child 函数(已更新以添加 SC_MAX_CHILD 的 sysconf() 值),因此进行了小幅改进:

  #include<stdio.h>
  #include<errno.h>
  #include<unistd.h>
  #include<stdlib.h>

   int main()
   {
       long int prc_id;
       printf("SC_CHILD_MAX = %d\n", sysconf(_SC_CHILD_MAX));

       prc_id=fork();

       if(prc_id ==0)
          calling_child();        
       else if(prc_id <0)
       {
           printf("errno - %d\n",errno); 
           printf("failed %d\n",prc_id);
           exit(0);
       }

      return 0;
     } 

   static void calling_child(void)
   {
      printf("Hello from PID %x\n", getpid());
      return;
   }

我将代码放在一个名为 test2.c 的文件中,并使用以下 shell 命令构建它:c99 -o test2 -g test2.c

它编译干净,我可以毫无问题地运行它。它产生这个输出:

SC_CHILD_MAX = 32767
Hello from PID 40100b2

很可能您的构建或执行环境配置不正确。它在我非常基本的系统上绝对可以正常工作,而且我根本不需要做任何不寻常的事情来让它运行。

一些小提示...

您是如何进入 z/OS UNIX shell 的?如果您登录到 TSO 然后运行 ​​ISPF shell 或 OMVS 命令,您可能更喜欢简单地通过 SSH 连接到您的 z/OS 系统。我通常发现这是最干净的批处理环境。

第二件事是您可能想要仔细检查您的 C/C++ 环境。 IBM XLC 编译器内置了一些很好的调试功能 - 尝试man C99(或您使用的任何方言)并阅读。

第三件事是 IBM 在 z/OS 中包含了 dbx 调试器,所以如果您真的遇到困难,只需尝试在 dbx 下运行您的可执行文件,您就可以一次单步执行您的程序行。

至于那些 ERRNO 等等,别忘了还要查看 __errno2() 值 - 它们通常有一个非常具体的原因代码,以及更通用的错误。例如,您的 z/OS 安全管理员当然可以做一些事情来限制您对 z/OS UNIX 功能的使用——这将在 __errno2() 值中非常清楚地显示出来。

坚持下去 - 如果您了解 UNIX 或 Linux,如果您花一点时间学习基础知识,那么从使用 shell 到编码的所有技能几乎都可以 100% 转移到 z/OS 上。

【讨论】:

  • 请进入sys1.sceeh.sys.h并检查为_SC_CHILD_MAX设置了什么值
  • 我相信你可能误解了_SC_CHILD_MAX的用法。
  • 这里有一个大问题 --> 在 unix shell 中(准确地说是在 /etc/profile 中)-> 行 for _CMP in _C89 _CC _CXX; do 被注释并且我没有编辑权限来取消 -评论它,因为在编译文件时我收到IKJ56228I DATA SET CEE.SCEELKEX NOT IN CATALOG OR CATALOG CAN NOT BE ACCESSED 错误并且我无法在 unix 环境中测试。虽然 MAXPROCSYS 是 4096 而 MAXPROCUSER 是 2048
  • 这里是其他值:sysconf(_SC_MAX_CHILD) -> -1, errno --&gt; a0000 errno2 --&gt; c10f0001 ------------- 这是代码在非unix中运行的时候环境。
  • 翻阅 IBM 的“z/OS UNIX 服务消息和代码”,发现没有“a000”错误,也没有 c10f0001 的 errno2,所以这里发生了更戏剧性的事情。
【解决方案2】:

如果您一直在使用fork(2),您很可能已经用尽了您的进程可用的进程限制,请参阅ulimit 以了解您的shell:

$ help ulimit | grep process
Ulimit provides control over the resources available to processes
    -d      the maximum size of a process's data segment
    -l      the maximum size a process may lock into memory
    -u      the maximum number of user processes

如果是这样,注销并重新登录将解决问题。

【讨论】:

  • 我不认为它可以在 Z/OS 上运行
  • @Joshua,他还剩 1 个进程。从 shell 调用编译器会使用该过程。一切都好。然后他运行他的程序,他也可以启动它,就像他可以启动编译器一样。然后它调用 fork(2),失败了。
  • @AgrudgeAmicus,IBM 似乎认为 z/OS 有分叉:ibm.com/support/knowledgecenter/en/SSLTBW_2.3.0/…。如果没有,他的系统严重错误配置了不支持的系统调用的头文件和库。
  • @JamesK.Lowden System 在一些当前正在运行的文件中有fork - 我认为您与 2 个进程有关的观点是正确的,而且我也在考虑同样的问题。但是还有另一个文件使用forkpthreads - 我猜线程系统会有所不同。
  • @JamesK.Lowden:不! cc 调用 ld。他们至少要编译两个。
猜你喜欢
  • 1970-01-01
  • 2013-05-12
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 2014-06-14
  • 1970-01-01
  • 1970-01-01
  • 2012-08-18
相关资源
最近更新 更多