Chapter 7. 范例程序

Table of Contents
捕获 SIGCHLD 信号
读取进程表 - SUNOS 4 版
读取进程表 - SYSV 版
读取进程表 - AIX 4.2 版
使用popen函数和ps命令读取进程表
守护程序工具函数
调制解调器控制范例程序
事务控制范例程序

捕获 SIGCHLD 信号

     #include <sys/types.h>  /* 在任何其它 sys 下的头文件之前引用这个头文件 */
     #include <sys/wait.h>   /* waitpid()和一些不同的宏所需的头文件 */
     #include <signal.h>     /* 信号函数的头文件 */
     #include <stdio.h>      /* fprintf函数的头文件 */
     #include <unistd.h>     /* fork函数的头文件 */   
     void sig_chld(int);     /* 我们的 SIGCHLD 信号处理函数的原形(prototype) */
    
     int main()
     {
         struct sigaction act;
         pid_t pid;
    
         /* 设定sig_chld函数作为我们SIGCHLD信号的处理函数 */
         act.sa_handler = sig_chld;
    
         /* 在这个范例程序里,我们不想阻塞其它信号 */
         sigemptyset(&amp;act.sa_mask);
    
         /*
          * 我们只关心被终止的子进程,而不是被中断
          * 的子进程 (比如用户在终端上按Control-Z)
          */
         act.sa_flags = SA_NOCLDSTOP;
    
         /*
          * 使这些设定的值生效. 如果我们是写一个真实的应用程序,
          * 我们也许应该保存这些原有值,而不是传递一个NULL。
          */
         if (sigaction(SIGCHLD, &act, NULL) < 0)
         {
             fprintf(stderr, "sigaction failed\n");
             return 1;
         }
    
         /* fork */
         switch (pid = fork())
         {
         case -1:
             fprintf(stderr, "fork failed\n");
             return 1;
    
         case 0:                         /* 是子进程,直接结束 */
             _exit(7);                   /* 退出状态 = 7 */
    
         default:                        /* 父进程 */
             sleep(10);                  /* 给子进程完成的时间 */
         }
    
         return 0;
     }
    
     /*
      * 信号处理函数 -- 只有当接收到一个SIGCHLD信号才被调用,
      * 即有一个子进程终止
      */
     void sig_chld(int signo)
     {
         int status, child_val;
    
         /* 非阻塞地等待任何子进程结束 */
         if (waitpid(-1, &status, WNOHANG) < 0)
         {
             /*
              * 不建议在信号处理函数中调用标准输入/输出函数,
              * 但在一个类似这个的玩具程序里或许没问题
              */
             fprintf(stderr, "waitpid failed\n");
             return;
         }
    
         /*
          * 我们现在有保存在‘status’变量中的子进程退出信息并可以使用
          * wait.h中定义的宏对其进行操作
          */
         if (WIFEXITED(status))                /* 子进程是正常退出吗? */
         {
             child_val = WEXITSTATUS(status); /* 获取子进程的退出状态 */
             printf("child's exited normally with status %d\n", child_val);
         }
     }