2016-10-07 1 views
0

Общие сведения и разъяснения о функционировании моей программы

Я написал программу, цель которой - создать процессы, пока она больше не сможет этого сделать (id est: она должна склеить ОС и полностью заполнить таблицу процессов). Однако, когда ОС склеивается, появляется сообщение «fork», и все процессы могут быть убиты конечным пользователем благодаря CTRL + Z.Как склеить систему благодаря процессам?

Моя программа содержит два важных процесса: главный, который создает второй. Первая называется «MAIN_P» в моем коде, а вторая «P_ROOT». Цель P_ROOT - fork, пока он больше не сможет этого сделать. Когда появляется ошибка fork (id est: когда моя программа преуспела!), Конечный пользователь может отправить сигнал CTRL-Z на MAIN_P, который убьет P_ROOT и его детей.

Я точно знаю, что P_ROOT и его дети имеют тот же GPID (наследование). Но последнее отличается от MAIN_P, конечно (setsid применяется к P_ROOT).


Моя проблема

Когда я запускаю свою программу, она fork первый ребенок, который fork своих детей до тех пор, пока операционная система наклеивается (то есть:., Пока таблица процессов не будет полностью заполнена). Единственная проблема в том, что я не могу CTRL + Z в моей консоли, чтобы остановить его ... И, конечно, если я просто выйду из терминала, он не убьет все эти процессы (а другие продолжают раздвоен кроме того).

Таким образом, я не рекомендую вам выполнять его ...

Что случилось с моим кодом?


Источник
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <sys/resource.h> 

int main(int argc, char* argv[]) { 
    pid_t pid_first_child = 0; 
    if((pid_first_child = fork()) == -1) { // We `fork` the first child, which will always `fork` (more precisely : until the OS is glued, processes table completely filled) 
     perror("fork"); 
     exit(EXIT_FAILURE); 
    } 

    if(pid_first_child == 0) { // BEGINNING OF <FirstChild>'S CODE 

     pid_t pid_session_leader = 0; 
     if((pid_session_leader = setsid()) == -1) { // FirstChild is its process group's leader 
      perror("setsid"); 
      exit(EXIT_FAILURE); 
     } 

     if(setpriority(PRIO_PGRP, pid_session_leader, -10) == -1) { // The priority of FirstChild (which is the group's leader) 
      perror("setpriority"); 
      exit(EXIT_FAILURE); 
     } 

     unsigned children_counter = 0; 
     pid_t pid_calculation_process = 0; 
     while((pid_calculation_process = fork()) != -1) { // Now, FirstChild will `fork` until the limit ! When the limit is reached, -1 is returned : there isn't anymore `fork` and we exit the loop 
      if(pid_calculation_process > 0) { 
       children_counter++; 
       fprintf(stdout, "%u\n", children_counter); 
      } else { // BEGINNING OF <FirstChild's children>'s CODE (Why ? Consequently to the `while` and the `if` !) 
       float j=1; 
       while(1) { // Children can't die 
        int i = 0; 
        for(; i < 1000; i++) { 
         j /= 3; 
        } 

        usleep(1000); 
       } 
      } // END OF <FirstChild's children>'s CODE (FirstChild's children) 
     } 
     perror("fork"); // It's what we wanted ! This message will tell the user "OS is glued, program worked correctly" 
     exit(EXIT_SUCCESS); // `EXIT_SUCCESS` ? Because we reached the limit ! 

    } // END OF <FirstChild>'S CODE 
} 
+0

Попробуйте использовать 'ULIMIT -u 50' установить лимит процесса перед запуском программы. Когда вы достигнете предела, вы должны получить ошибку. – Barmar

+0

Подсказка: ваш // nota bene не имеет большого смысла. Когда люди используются, что «p_» имеет определенное значение, то ** dont ** «переопределяет это значение. Такие первоначальные комментарии будут упущены раньше или позже. Значение: ** никогда ** не вводить код, который мог бы * удивить * его читатели! – GhostCat

+0

@Barmar: Я не хочу устанавливать предел процесса на самом деле. Я действительно хочу полностью заполнить таблицу процессов и приклеить ОС. Тем не менее, я хочу иметь возможность в терминале CTRL + Z убить все процессы и, таким образом, освободить таблицу процессов. –

ответ

1

Комментарии:

  • Чтобы достичь вилку() ограничить быстро, вы должны убедиться, что каждый раздвоенный процесс не потребляет слишком много ресурсов. Ваши разветвленные процессы вращаются в for-loop и занимают слишком много ресурсов. Если вы удалите for-loop, вы быстрее достигнете предела процесса, так как процессы будут заблокированы при вызове sleep() вместо вращения.
  • Вам не нужен цикл ожидания, чтобы дождаться завершения процессов после ошибки fork(). Это произойдет автоматически.

Обновленный источник:

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

int main(int argc, char* argv[]) { 
    // This (first !) child, say "P_ROOT", will create its own children, which will glue the system (thus, MAIN_P is freed 
    int p_root = fork(); 
    if(p_root == -1) { 
     perror("fork"); 
     exit(EXIT_FAILURE); 
    } 
    // P_ROOT's PGID will be set to its PID (so we have : P_ROOT's PGID != MAIN_P's PGID) 
    if (p_root == 0) { 
     if(setpgid(p_root, p_root) == -1) { 
      perror("setpgid"); 
      exit(EXIT_FAILURE); 
     } 

     int p_root_number_of_created_children = 0; 
     pid_t p_root_child = 0; 
     while((p_root_child = fork()) != -1) { // P_ROOT forks until it can't do it anymore... 
      if(p_root_child != 0) { 
      p_root_number_of_created_children++; 
      } else { 
#ifdef CONSUME_RESOURCES 
      int i = 0; 
      while(i < 1000000000000000000) { 
       i++; 
      } 
#endif 
      sleep(6000); 
      exit(EXIT_FAILURE); 
      } 
     } 

     // NOW it's impossible to create new child processes 
     perror("fork"); 
     fprintf(stdout, "\nImpossible to create more children. Their number is : %d\n", p_root_number_of_created_children); 
     exit(EXIT_SUCCESS); 
    } else { 
     printf("Waiting, top level, root = %d\n", p_root); 
     wait(NULL); // MAIN_P waits for P_ROOT 

     char cmd = 0; 

     if(scanf("%c", &cmd) < 0) { 
      perror("scanf"); 
      exit(EXIT_FAILURE); 
     } 

     if(cmd == '\n' && kill(-p_root, SIGKILL) == -1) { 
      perror("kill"); 
      exit(EXIT_FAILURE); 
     } 

     exit(EXIT_SUCCESS); 
    } 
} 
+0

С вашим (и моим) кодом я не смог убить свои процессы с помощью '\ n' или CTRL + Z. Я написал еще один код, короче. С этим новым я даже не могу сделать CTRL + Z (по-видимому, этот терминал игнорируется), и, конечно же, процесс не убит. Более того, 'fork' новых процессов продолжается: у меня нет никакого контроля над моей ОС, который я должен перезапускать каждый раз при выполнении моей программы ... (к счастью, я использую VB). Не могли бы вы взглянуть на мой новый короткий код, пожалуйста? Я подробно прокомментировал это. –

+0

Примечание: Я хотел написать CTRL + C, а не CTRL + Z (не могу отредактировать мой комментарий извините) –

 Смежные вопросы

  • Нет связанных вопросов^_^