Advertisement
anticlown

Lab_8(processes and signals)

Dec 9th, 2023 (edited)
715
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.67 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <time.h>
  5. #include <signal.h>
  6. #include <sys/wait.h>
  7. #include <stdbool.h>
  8.  
  9. #define PROC_COUNT 9 // общее кол-во процессов. Нулевой(исходный) + 8 дочерних
  10.  
  11. static int processSelfNumber = 1; // номер выбранного на данный момент процесса
  12. static int USR1 = 0;              // счетчик сигналов USR1
  13. static int USR2 = 0;              // счетчик сигналов USR2
  14. static bool isTerminated = false;
  15. pid_t arrOfPIDs[PROC_COUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // массив для хранения процессов
  16.  
  17. void printProcessInfo(const int signalValue)
  18. {
  19.     printf("\t>> Процесс №%d (PID: %d, PPID: %d) получил сигнал %s за время %ld мксек\n\n", processSelfNumber, getpid(), getppid(), (signalValue == SIGUSR1) ? "SIGUSR1" : "SIGUSR2", clock());
  20. }
  21.  
  22. void createGroup(const int parentIndex, const int firstProcessIndex, const int lastProcessIndex)
  23. {
  24.     for (int i = firstProcessIndex; i <= lastProcessIndex; i++)
  25.         setpgid(arrOfPIDs[i], arrOfPIDs[firstProcessIndex]);
  26.  
  27.     printf("\n\tБыла создана группа процессов %d..%d\n\n", firstProcessIndex, lastProcessIndex);
  28. }
  29.  
  30. void sendSignalToProcess(const int processNumber, const int signalValue, const int signalCounter)
  31. {
  32.     for (int h = 1; h <= signalCounter; h++)
  33.     {
  34.         kill(arrOfPIDs[processNumber], signalValue);
  35.         printf("\tПроцесс №%d (PID: %d, PPID: %d) послал сигнал %s прцоессу №%d за время %ld >>\n\n", processSelfNumber, getpid(), getppid(), (signalValue == SIGUSR1) ? "SIGUSR1" : "SIGUSR2", processNumber, clock());
  36.         usleep(100000);
  37.     }
  38.     kill(arrOfPIDs[processNumber], SIGTERM);
  39. }
  40.  
  41. void sendSignalToGroup(const int groupMemberNumber, const int signalValue, const int signalCounter)
  42. {
  43.     for (int h = 1; h <= signalCounter; h++)
  44.     {
  45.         killpg(arrOfPIDs[groupMemberNumber], signalValue);
  46.         printf("\tПроцесс №%d (PID: %d, PPID: %d) послал сигнал %s группе %d за время %ld >>\n\n", processSelfNumber, getpid(), getppid(), (signalValue == SIGUSR1) ? "SIGUSR1" : "SIGUSR2", groupMemberNumber, clock());
  47.         usleep(100000);
  48.     }
  49.     killpg(arrOfPIDs[groupMemberNumber], SIGTERM);
  50. }
  51.  
  52. void signalHandler(const int signalValue)
  53. {
  54.     usleep(clock());
  55.     switch (signalValue)
  56.     {
  57.     case SIGUSR1:
  58.         printProcessInfo(signalValue);
  59.         USR1++;
  60.         break;
  61.     case SIGUSR2:
  62.         printProcessInfo(signalValue);
  63.         USR2++;
  64.         break;
  65.     default:
  66.         printf("\t>> Процесс №%d (PID: %d, PPID: %d) получил сигнал SIGTERM за время %ld мксек\n\n", processSelfNumber, getpid(), getppid(), clock());
  67.         isTerminated = true;
  68.         break;
  69.     }
  70. }
  71.  
  72. void waitTillEnd()
  73. {
  74.     for (int i = 0; i < PROC_COUNT; i++)
  75.         wait(NULL);
  76.        
  77.     printf("\t\t\tПроцесс №%d (PID: %d, PPID: %d) закончил работу после %d-го сигнала SIGUSR1 и %d-го сигнала SIGUSR2\n\n", processSelfNumber, getpid(), getppid(), USR1, USR2);
  78. }
  79.  
  80. void createProcess(const int childProcessNumber, pid_t pid)
  81. {
  82.     pid = fork();
  83.     if (pid == 0)
  84.     {
  85.         processSelfNumber = childProcessNumber;
  86.     }
  87.     if (pid > 0)
  88.         arrOfPIDs[childProcessNumber] = pid;
  89. }
  90.  
  91. void createProcessesTree(const int SIGNUM)
  92. {
  93.     pid_t pid = fork(); // создание 0-го процесса
  94.  
  95.     if (pid == 0) // если процесс - дочерний
  96.     {
  97.         /*
  98.             Дерево процессов
  99.             1->2
  100.                 2->3
  101.                     3->(4,5,6)
  102.                         4->8
  103.                         6->7
  104.         */
  105.  
  106.         arrOfPIDs[processSelfNumber] = getpid();
  107.         createProcess(2, pid);
  108.  
  109.         if (processSelfNumber == 2)
  110.         {
  111.             arrOfPIDs[processSelfNumber] = getpid();
  112.             createProcess(3, pid);
  113.         }
  114.  
  115.         if (processSelfNumber == 3)
  116.         {
  117.             arrOfPIDs[processSelfNumber] = getpid();
  118.             for (int i = 4; i <= 6; i++)
  119.             {
  120.                 pid = fork();
  121.                 if (pid == 0)
  122.                 {
  123.                     processSelfNumber = i;
  124.                     break;
  125.                 }
  126.                 if (pid > 0)
  127.                     arrOfPIDs[i] = pid;
  128.             }
  129.         }
  130.  
  131.         if (processSelfNumber == 4)
  132.         {
  133.             arrOfPIDs[processSelfNumber] = getpid();
  134.             createProcess(8, pid);
  135.         }
  136.  
  137.         if (processSelfNumber == 6)
  138.         {
  139.             arrOfPIDs[processSelfNumber] = getpid();
  140.             createProcess(7, pid);
  141.         }
  142.  
  143.         printf("\tПроцесс №%d (PID: %d, PPID: %d) создан\n", processSelfNumber, getpid(), getppid());
  144.         usleep(100000);
  145.  
  146.         // создание группы процессов 3->(4-6)
  147.         if (processSelfNumber == 3)
  148.         {
  149.         arrOfPIDs[processSelfNumber] = getpid();
  150.             createGroup(3, 4, 6);
  151.         }
  152.  
  153.         signal(SIGUSR1, signalHandler);
  154.         signal(SIGUSR2, signalHandler);
  155.         signal(SIGTERM, signalHandler);
  156.  
  157.         usleep(100000);
  158.  
  159.         /*
  160.             последовательность обмена сигналами
  161.             1->(8,7,6)SIGUSR1
  162.                 8->4 SIGUSR1
  163.                 7->4 SIGUSR2
  164.                 6->4 SIGUSR1
  165.                     4->(3,2)SIGUSR1
  166.                         2->1 SIGUSR2
  167.         */
  168.         switch (processSelfNumber)
  169.         {
  170.         case 1:
  171.             sendSignalToGroup(6, SIGUSR1, SIGNUM);
  172.             break;
  173.         case 8:
  174.             sendSignalToProcess(4, SIGUSR1, SIGNUM);
  175.             break;
  176.         case 7:
  177.             sendSignalToProcess(4, SIGUSR2, SIGNUM);
  178.             break;
  179.         case 6:
  180.             sendSignalToProcess(4, SIGUSR1, SIGNUM);
  181.             break;
  182.         case 4:
  183.             sendSignalToGroup(2, SIGUSR1, SIGNUM);
  184.             break;
  185.         case 2:
  186.             sendSignalToProcess(1, SIGUSR2, SIGNUM);
  187.             break;
  188.         }
  189.  
  190.         waitTillEnd();
  191.     }
  192.     else
  193.     {
  194.         printf("\n\t####### Процесс №0 (PID: %d, PPID: %d) #######\n\n", getpid(), getppid());
  195.         wait(NULL);
  196.     }
  197. }
  198.  
  199. int main(int argc, char *argv[])
  200. {
  201.     const int NUM_OF_ARGS = 2;
  202.     if (argc < NUM_OF_ARGS)
  203.     {
  204.         fprintf(stderr, "Использование: %s <количество сигналов>\n", argv[0]);
  205.         return EXIT_FAILURE;
  206.     }
  207.  
  208.     createProcessesTree(atoi(argv[1]));
  209.  
  210.     return EXIT_SUCCESS;
  211. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement