2

我想测试是否通过多个进程我能够在 32 位操作系统上使用超过 4GB 的内存(我的:带有 1GB 内存的 Ubuntu)。

因此,我编写了一个 malloc 略小于 1GB 的小程序,并对该数组执行了一些操作,并运行了该程序的 5 个实例 vie forks。

问题是,我怀疑操作系统杀死了其中的 4 个,只有一个幸存下来并显示它是“PID:我已经完成”)。

(我用小数组尝试过,打印了 5 次,当我用 TOP 查看正在运行的进程时,我只看到一个实例..)

奇怪的是 - 我在所有实例中都收到了返回代码 0(成功?),包括那些据称被操作系统杀死的实例

我没有得到任何说明进程被杀死的消息。

这个返回码在这种情况下正常吗?

(如果是这样,它会降低我对“返回码”的信任......)

谢谢。

编辑:一些答案暗示了小程序中可能存在的错误,所以在这里。分叉和保存返回码的较大程序较大,我无法在这里上传它,但我认为(并希望)它很好。

我还注意到,如果不是使用我的分叉程序运行它,而是使用终端运行它,使用 './a.out & ./a.out & ./a.out & ./a.out &' (当./a.out 是附加的小程序的二进制文件)我确实看到了一些“Killed”消息。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#define SMALL_SIZE 10000
#define BIG_SIZE 1000000000
#define SIZE BIG_SIZE
#define REAPETS 1

    int
main()
{
    pid_t my_pid = getpid();

    char * x = malloc(SIZE*sizeof(char));

    if (x == NULL)
    {
            printf("Malloc failed!");
            return(EXIT_FAILURE);
    }

    int x2=0;
    for(x2=0;x2<REAPETS;++x2)
    {
            int y;
            for(y=0;y<SIZE;++y)
                    x[y] = (y+my_pid)%256;
    }
    printf("%d: I'm over.\n",my_pid);
    return(EXIT_SUCCESS);
}
4

6 回答 6

5

使用什么信号来终止进程?

0到127(含)之间的退出代码可以自由使用,128以上的代码表示进程被信号终止,其中退出代码为

128 + 使用的信号数

于 2009-04-12T21:07:11.067 回答
5

好吧,如果您的进程无法malloc()使用 1GB 内存,操作系统不会杀死该进程。所发生的只是malloc()返回 NULL。因此,根据您编写代码的方式,该进程可能无论如何都会返回 0 - 如果您希望它在内存分配失败时返回错误代码(这通常是一种好习惯),您必须将该行为编程为它。

于 2009-04-12T21:07:43.047 回答
4

进程的返回状态(由wait,waitpid和返回system)或多或少包含以下内容:

  • 退出代码,仅在进程正常终止时适用
  • 是否发生正常/异常终止
  • 终止信号,仅在进程被信号终止时适用

如果您的进程被 OOM 杀手杀死(这显然会向您发送 SIGKILL 信号),则退出代码完全没有意义

有关详细信息,请参阅wait命令的手册页。

于 2009-04-12T21:14:29.723 回答
3

此代码显示如何获取孩子的终止状态:

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

#include <unistd.h>
#include <sys/wait.h>

int
main (void)
{ 
  pid_t pid = fork();

  if (pid == -1)
  {
    perror("fork()");
  }
  /* parent */
  else if (pid > 0)
  {
    int status;

    printf("Child has pid %ld\n", (long)pid);

    if (wait(&status) == -1)
    {
      perror("wait()");
    }
    else
    {
      /* did the child terminate normally? */
      if(WIFEXITED(status))
      {
        printf("%ld exited with return code %d\n",
               (long)pid, WEXITSTATUS(status));
      }
      /* was the child terminated by a signal? */
      else if (WIFSIGNALED(status))
      {
        printf("%ld terminated because it didn't catch signal number %d\n",
               (long)pid, WTERMSIG(status));
      }
    }
  }
  /* child */
  else
  {
    sleep(10);
    exit(0);
  }

  return 0;
}
于 2009-04-14T14:22:30.087 回答
1

你检查过返回值fork()吗?很有可能如果fork()无法为新进程的地址空间分配足够的内存,那么它将返回错误 (-1)。一个典型的调用方式fork()是:

pid_t pid;
switch(pid = fork())
{
case 0:
    // I'm the child process
    break;
case -1:
    // Error -- check errno
    fprintf(stderr, "fork: %s\n", strerror(errno));
    break;
default:
    // I'm the parent process
}
于 2009-04-12T21:15:02.670 回答
1

仅当 WIFEXITED 宏评估为真时,退出代码才“有效”。请参阅man waitpid(2)

您可以使用 WIFSIGNALED 宏来查看您的程序是否已收到信号。

于 2009-04-13T10:31:56.047 回答