【问题标题】:Print Odd-Even numbers using signals使用信号打印奇偶数
【发布时间】:2008-08-29 21:52:57
【问题描述】:

我需要打印自然编号。 1,2,...n 这样父进程打印所有奇数,子进程打印所有偶数,所有这些都需要使用 POSIX 信号来完成。我将如何实现这一目标?

输出应该是:

家长:1
儿童:2
家长:3
...

【问题讨论】:

    标签: c signals


    【解决方案1】:

    如果你提供你目前所拥有的东西并解释什么不能按预期工作,这可能对你更有益,但这是我想出的:

    #include <stdio.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <signal.h>
    #include <stdlib.h>
    
    #define READY_SIGNAL SIGUSR1
    
    /* The ready flag is set when READY_SIGNAL is received.
     * It is needed so that when we wake up from sigsuspend
     * we know whether or not the signal received was READY_SIGNAL. */
    volatile sig_atomic_t ready;
    void make_ready(int i) { ready = 1; }
    
    int
    main (int argc, char *argv[])
    {
      pid_t cpid, ppid;  /* pids of the child and parent */
      /* Signal masks for sigprocmask and sigsuspend */
      sigset_t block_mask, wait_mask;
      unsigned long c = 1;   /* The counter */
      unsigned long n = 100; /* The default max count value */
      struct sigaction act;
    
      /* Override the default max count if provided */
      if (argv[1])
        n = strtoul(argv[1], NULL, 10);
    
      /* Prepare signal masks */
      sigemptyset(&wait_mask);
      sigemptyset(&block_mask);
      sigaddset(&block_mask, READY_SIGNAL);
    
      /* Set the signal mask for the parent to ignore READY_SIGNAL until
       * we are ready to receive it, the mask will be inherited by the child,
       * needed to avoid race conditions */
      sigprocmask(SIG_BLOCK, &block_mask, NULL);
    
      /* Register the signal handler, will be inherited by the child */
      act.sa_flags = 0;
      act.sa_handler = make_ready;
      sigemptyset(&act.sa_mask);
      sigaction(READY_SIGNAL, &act, NULL);
    
      /* Get the parent's process id, needed for the child to send signals
       * to the parent process, could alternatively use getppid in the child */
      ppid = getpid();
    
      /* Call fork, storing the child's process id needed for the parent to
       * send signals to the child */
      cpid = fork();
    
      if (cpid < 0) {
        perror("Fork failed");
        exit(EXIT_FAILURE);
      }
    
      if (cpid == 0) {
        /* Child */
        c = 2;  /* Child's first number will always be 2 */
        if (c > n) exit(0); /* If c > n we have nothing to do */
    
        do {
          /* Suspend until we receive READY_SIGNAL */
          while (!ready) sigsuspend(&wait_mask);
    
          /* Print out number, flush for proper output sequencing when output
             is not a terminal. */
          printf("Child: %lu\n", c);
          fflush(stdout);
    
          ready = 0; /* Reset ready flag */
          c += 2; /* Increment counter */
    
          /* Wake up parent process */
          kill(ppid, READY_SIGNAL);
        } while (c <= n);  
      } else {
        /* Parent */
        for (;;) {
          /* Print out number, flush for proper output sequencing when output
             is not a terminal. */
          printf("Parent: %lu\n", c);
          fflush(stdout);
    
          c += 2; /* Increment counter */
    
          kill(cpid, READY_SIGNAL); /* Wake up child process */
    
          if (c > n) break; /* Don't go back to sleep if we are done */
    
          ready = 0; /* Reset ready flag */
    
          /* Suspend until we receive READY_SIGNAL */
          while (!ready) sigsuspend(&wait_mask);
        };
    
        wait4(cpid, NULL, 0); /* Don't exist before child finishes */
      }
    
      return 0;
    }
    

    这通过了这些基本测试:

    ./print_with_signals 100000|sort -n -k 2 -c &amp;&amp; echo "Success"
    ./print_with_signals 100001|sort -n -k 2 -c &amp;&amp; echo "Success"

    【讨论】:

      【解决方案2】:

      我认为给你这个家庭作业是为了让你尝试很多解决方案并自己得出结论信号不是一种好的同步技术

      这是非常宝贵的一课,记住它,从现在开始使用信号量! :)

      【讨论】:

        猜你喜欢
        • 2011-08-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多