Код возврата, когда ОС убивает ваш процесс

Я хотел проверить, могу ли я с несколькими процессами использовать более 4 ГБ оперативной памяти в 32-битной ОС (мой: Ubuntu с 1 ГБ оперативной памяти).

Итак, я написал небольшую программу, которая использует malloc чуть меньше 1 ГБ, выполняет некоторые действия с этим массивом и запускает 5 экземпляров этой программы для разветвления.

Дело в том, что я подозреваю, что ОС убила 4 из них, а выжил только один и выдал "PID: Я закончил").

(Я пробовал это с небольшими массивами и получил 5 распечаток, также, когда я смотрю на запущенные процессы с помощью TOP, я вижу только один экземпляр..)

Странно вот что: я получил код возврата 0 (успех?) во ВСЕХ экземплярах, включая те, которые якобы были убиты ОС.

Я не получил никакого сообщения о том, что процессы были убиты.

Является ли этот код возврата нормальным для данной ситуации?

(Если это так, это снижает мое доверие к «кодам возврата»…)

благодаря.

Редактировать: некоторые ответы предполагали возможные ошибки в небольшой программе, так что вот она. большая программа, которая разветвляет и сохраняет коды возврата, больше, и у меня возникли проблемы с загрузкой ее сюда, но я думаю (и надеюсь), что все в порядке.

Также я заметил, что если вместо того, чтобы запускать его с моей программой разветвления, я запускаю его с помощью терминала, используя «./a.out & ./a.out & ./a.out & ./a.out &» (когда ./a.out — это двоичный файл прикрепленной небольшой программы) Я вижу несколько сообщений «Убито».

#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);
}

person Liran Orevi    schedule 12.04.2009    source источник


Ответы (6)


Статус возврата процесса (возвращаемый wait, waitpid и system) содержит более или менее следующее:

  • Код выхода, применяется только в том случае, если процесс завершился нормально
  • произошло ли нормальное/ненормальное завершение
  • Сигнал завершения, применяется только в том случае, если процесс был завершен сигналом

Код выхода совершенно бессмысленен, если ваш процесс был убит убийцей OOM (который, по-видимому, отправит вам сигнал SIGKILL)

для получения дополнительной информации см. справочную страницу команды wait.

person Hasturkun    schedule 12.04.2009
comment
хороший ответ, вы можете добавить пример кода, чтобы сделать его еще лучше :-) - person lothar; 13.04.2009

Ну, если ваш процесс не может malloc() 1 ГБ памяти, ОС не уничтожит процесс. Все, что происходит, это то, что malloc() возвращает NULL. Таким образом, в зависимости от того, как вы написали свой код, возможно, что процесс все равно вернет 0 - если вы хотите, чтобы он возвращал код ошибки при сбое выделения памяти (что обычно является хорошей практикой), вам нужно запрограммировать это поведение в Это.

person David Z    schedule 12.04.2009
comment
Не совсем верно. Linux позволяет процессам перераспределять память, а затем убивает процессы, когда на самом деле используется слишком много памяти. - person nobody; 13.04.2009
comment
Но это все еще предположение, единственный способ узнать это — использовать один из системных вызовов ожидания, как упомянул Хастуркун, и проверить статус, а также код возврата. - person lothar; 13.04.2009
comment
Спасибо, но я проверяю NULL и печатаю красивое сообщение, которое не печатается. - person Liran Orevi; 13.04.2009
comment
Залил небольшую программу, если интересно. - person Liran Orevi; 13.04.2009

Какой сигнал использовался для уничтожения процессов?

Коды выхода от 0 до 127 включительно можно использовать свободно, а коды выше 128 указывают на то, что процесс был завершен сигналом, где код выхода

128 + номер используемого сигнала

person Mihai Limbășan    schedule 12.04.2009

Этот код показывает, как получить статус завершения дочернего элемента:

#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;
}
person Bastien Léonard    schedule 14.04.2009

Вы проверили возвращаемое значение от 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
}
person Adam Rosenfield    schedule 12.04.2009
comment
Спасибо, в моем случае, однако, я проверяю это. - person Liran Orevi; 13.04.2009

Код выхода является «действительным», только если макрос WIFEXITED оценивается как true. См. man waitpid(2).

Вы можете использовать макрос WIFSIGNALED, чтобы увидеть, была ли сигнализирована ваша программа.

person Paweł Hajdan    schedule 13.04.2009