Advertisement
srokoszr

SOP1 - lab2 - kod Grześka

Jan 24th, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.05 KB | None | 0 0
  1. #define _GNU_SOURCE
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <signal.h>
  5. #include <time.h>
  6. #include <sys/wait.h>
  7. #include <errno.h>
  8. #include <string.h>
  9. #include <unistd.h>
  10. #include <sys/stat.h>
  11. #include <fcntl.h>
  12.  
  13. #define ERR(source) (fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
  14.                      perror(source),kill(0,SIGKILL),\
  15.                                      exit(EXIT_FAILURE))
  16. #define CHILDREN_COUNT 3
  17. #define CHILD_DELAY_MIN 3
  18. #define CHILD_DELAY_MAX 7
  19. #define BLOCK_SIZE 3000
  20.  
  21. void usage(char *name) {
  22.         fprintf(stderr,"USAGE: %s t1 t2 t3\n",name);
  23.         fprintf(stderr,"200 <= t1, t2, t3 <= 250\n");
  24.         exit(EXIT_FAILURE);
  25. }
  26.  
  27. void shuffle(int *array, size_t n)
  28. {
  29.     if (n > 1)
  30.     {
  31.         size_t i;
  32.         for (i = 0; i < n - 1; i++)
  33.         {
  34.           size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
  35.           int t = array[j];
  36.           array[j] = array[i];
  37.           array[i] = t;
  38.         }
  39.     }
  40. }
  41.  
  42. void setHandler(int signal, void (*handler)(int)) {
  43.         struct sigaction action;
  44.         memset(&action, 0, sizeof(action));
  45.         action.sa_handler = handler;
  46.         if (sigaction(signal, &action, NULL) == -1)
  47.                 ERR("sigaction");
  48. }
  49.  
  50. volatile sig_atomic_t childrenLeft = 0;
  51. void handleZombie() {
  52.         while (1) {
  53.                 pid_t pid = waitpid(0, NULL, WNOHANG);
  54.                 if (pid < 0) {
  55.                         if (errno == ECHILD)
  56.                                 return;
  57.                         ERR("waitpid");
  58.                 }
  59.                 if (pid == 0)
  60.                         return;
  61.  
  62.                 childrenLeft--;
  63.         }
  64. }
  65.  
  66. void generateRandomLettersBlock(char *buffer, ssize_t size) {
  67.         int i,
  68.                 alphabetLength = 'Z' - 'A' + 1;
  69.         for (i=0; i < size-1; i++)
  70.                 buffer[i] = 'A' + rand() % alphabetLength;
  71.         buffer[size - 1] = '\0';
  72. }
  73.  
  74. ssize_t bulkWrite(int fd, char *buf, size_t count) {
  75.         ssize_t bytesWritten = 0;
  76.         ssize_t totalBytesWritten = 0;
  77.         while (count > 0) {
  78.                 bytesWritten = TEMP_FAILURE_RETRY(write(fd, buf, count));
  79.                 if (bytesWritten < 0)
  80.                         return bytesWritten;
  81.                 totalBytesWritten += bytesWritten;
  82.                 buf += bytesWritten;
  83.                 count -= bytesWritten;
  84.         }
  85.  
  86.         return totalBytesWritten;
  87. }
  88.  
  89. volatile sig_atomic_t signalsReceived[CHILDREN_COUNT];
  90. void handleSignal(int signal) {
  91.         int i;
  92.         for (i=CHILDREN_COUNT-1; i > 0; --i)
  93.                 signalsReceived[i] = signalsReceived[i-1];
  94.         signalsReceived[0] = signal;
  95. }
  96.  
  97. void childTimeout() {
  98.         printf("[%d] terminates by alarm\n", getpid());
  99.         exit(EXIT_SUCCESS);
  100. }
  101.  
  102. void childWorker(int t, int signalToSend) {
  103.         srand(getpid());
  104.         int s = CHILD_DELAY_MIN + rand() % (CHILD_DELAY_MAX - CHILD_DELAY_MIN + 1);
  105.         printf("[%d] s = %d, t = %d, signalToSend = %d\n", getpid(), s, t, signalToSend);
  106.  
  107.         setHandler(SIGALRM, childTimeout);
  108.         alarm(s);
  109.  
  110.         struct timespec timeLeft;
  111.         while (1) {
  112.                 timeLeft.tv_sec = 0;
  113.                 timeLeft.tv_nsec = t * 1000 * 1000;
  114.                 while (nanosleep(&timeLeft, &timeLeft) != 0)
  115.                         continue;
  116.  
  117.                 printf("[%d] sends %d\n", getpid(), signalToSend);
  118.                 kill(getppid(), signalToSend);
  119.         }
  120. }
  121.  
  122. void parentWorker(int signalsToReceive[], char *outputFileName) {
  123.         srand(getpid());
  124.  
  125.         // Set SIG_BLOCK on signals to receive
  126.         sigset_t blockMask, oldMask;
  127.         sigemptyset(&blockMask);
  128.  
  129.         int i;
  130.         for (i=0; i < CHILDREN_COUNT; i++)
  131.                 sigaddset(&blockMask, signalsToReceive[i]);
  132.  
  133.         if (sigprocmask(SIG_BLOCK, &blockMask, &oldMask) != 0)
  134.                 ERR("sigprocmask");
  135.  
  136.         // Add handlers for those signals
  137.         for (i=0; i < CHILDREN_COUNT; i++)
  138.                 setHandler(signalsToReceive[i], handleSignal);
  139.  
  140.         // Shuffle signals to receive array
  141.         shuffle(signalsToReceive, CHILDREN_COUNT);
  142.         printf("[PARENT=%d] started\n", getpid());
  143.  
  144.         for (i=0; i < CHILDREN_COUNT; i++)
  145.                 printf("[PARENT=%d] %d signal to receive = %d\n", getpid(), i+1, signalsToReceive[i]);
  146.  
  147.  
  148.         char *buffer = malloc((BLOCK_SIZE + 2) * sizeof(char));
  149.         if (buffer == NULL)
  150.                 ERR("malloc");
  151.  
  152.         int outputFd = TEMP_FAILURE_RETRY(open(outputFileName, O_WRONLY | O_CREAT | O_TRUNC, 0777));
  153.         if (outputFd < 0)
  154.                 ERR("open");
  155.  
  156.         while (childrenLeft > 0) {
  157.                 sigsuspend(&oldMask);
  158.  
  159.                 int unmatchedSignal = 0;
  160.                 for (i=0; i < CHILDREN_COUNT; i++) {
  161.                         if (signalsReceived[i] != signalsToReceive[i]) {
  162.                                 unmatchedSignal = 1;
  163.                                 break;
  164.                         }
  165.                 }
  166.                 printf("[PARENT=%d] last signals: %d", getpid(), signalsReceived[0]);
  167.                 for (i=1; i < CHILDREN_COUNT; i++)
  168.                         printf(", %d", signalsReceived[i]);
  169.                 printf("\nRequested order: %d", signalsToReceive[0]);
  170.                 for (i=1; i < CHILDREN_COUNT; i++)
  171.                         printf(", %d", signalsToReceive[i]);
  172.                 printf("\n");
  173.  
  174.                 if (!unmatchedSignal) {
  175.                         // Signals match
  176.                         printf("[PARENT=%d] signals match\n", getpid());
  177.  
  178.  
  179.                         generateRandomLettersBlock(buffer, BLOCK_SIZE+1);
  180.                         printf("[PARENT=%d] random letters block:\n", getpid());
  181.                         printf("%s", buffer);
  182.                         bulkWrite(outputFd, buffer, BLOCK_SIZE);
  183.                 }
  184.         }
  185.         if (TEMP_FAILURE_RETRY(close(outputFd)) == -1)
  186.                 ERR("close");
  187.         free(buffer);
  188. }
  189.  
  190.  
  191. int main(int argc, char **argv) {
  192.         if (argc != CHILDREN_COUNT+2)
  193.                 usage(argv[0]);
  194.  
  195.         int t[CHILDREN_COUNT],
  196.                 i,
  197.                 signalsToSend[CHILDREN_COUNT] = { 10, 12, 16 };
  198.         for (i=0; i < CHILDREN_COUNT; i++) {
  199.                 t[i] = atoi(argv[i+1]);
  200.                 if (t[i] < 200 || t[i] > 250)
  201.                         usage(argv[0]);
  202.         }
  203.  
  204.         char *outputFileName = argv[CHILDREN_COUNT+1];
  205.  
  206.  
  207.         setHandler(SIGCHLD, handleZombie);
  208.         for (i=0; i < CHILDREN_COUNT; i++)
  209.                 setHandler(signalsToSend[i], SIG_IGN);
  210.  
  211.         for (i=0; i < CHILDREN_COUNT; i++) {
  212.                 pid_t pid = fork();
  213.                 if (pid < 0)
  214.                         ERR("fork");
  215.                 if (pid == 0)
  216.                         childWorker(t[i], signalsToSend[i]);
  217.         }
  218.         childrenLeft = CHILDREN_COUNT;
  219.  
  220.         // Parent
  221.         parentWorker(signalsToSend, outputFileName);
  222.         while (wait(NULL) > 0)
  223.                 continue;
  224.         printf("[PARENT=%d] terminates\n", getpid());
  225.         return EXIT_SUCCESS;
  226. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement