LoveUnix » 编程开发 & Rational » UNIX下信号问题
让LU留住您的每

一天 让LU博客留住您的每一天
2007-9-25 10:52 cy0space
UNIX下信号问题

最近在学习unix下的信号,以下有一个小程序.
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<sys/msg.h>
#include<sys/wait.h>

#define G_FORK_MIN   5
#define SYS_FORK_SIZE 100
  
int pid=0,ch_pid=0;
int shut_flag=0,signal_flag=0;
int g_curr_fork=0;
int g_chldpid[SYS_FORK_SIZE];

int daemon_init(char *file)
{
   FILE *fp;
   pid_t pid;
   char fn[80];

   if((pid=fork())<0)
   {
      printf("Fork Error! [%s] shotdown...\n", file);
      exit(1);
   }
   memset(fn,0,sizeof(fn));
   sprintf(fn, "%s/%s/%s.pid", (char *) getenv("HOME"), "pid", file);

   if((fp=fopen(fn,"w+"))==NULL)
      printf("%s : ERROR OPEN PID FILE!\n",fn);

   if(pid)
   {
     exit(0);
   }
   setsid();
   chdir("/");
   umask(027);
   fprintf(fp,"%d\n",getpid());
   fclose(fp);
   return 0;
}


void sig_chld(int sig_no)
{
       int i=0;
       int staloc=0;
      
       printf("signal SIGCHLD[%d] received!\n",sig_no);
       pid=waitpid(-1,&staloc,WNOHANG);
       while( pid<0 )
        {
               /*避免出现僵尸进程,调用该函数来终止子进程*/
               pid=waitpid(-1,&staloc,WNOHANG);
        }
       /*waitpid函数返回子进程id表示成功,-1表示失败*/
  printf("wait pid[%d]\n",pid);
  
  for(i=0;i<SYS_FORK_SIZE;i++)
  {
         if( g_chldpid[i]==pid )
                {
                       g_chldpid[i]=-1;
                       break;
                }
  }
  
  g_curr_fork--;
  signal_flag=1;      
}


void sig_term(int sig_no)
{
       int i=0;
      
       pid=0;
       pid=getpid();
      
       printf("signal SIGTERM[%d] received by pid[%d]\n",SIGTERM,pid);
       signal_flag=1;
      
       for(i=0;i<SYS_FORK_SIZE;i++)
       {
              if( g_chldpid[i]!=-1 )
                     {
                            kill(g_chldpid[i],SIGTERM);
                            g_curr_fork--;
                     }
       }
       shut_flag=1;
}


void sig_term_ch(int signo)
{
       pid=0;
       pid=getpid();
       printf("chld[%d] receive signal term_ch[%d]\n",pid,SIGTERM);
      
       exit(1);
}



void main(int argc,char *argv[])
{
       int i=0;
              
       printf("this is a test\n");
      
       daemon_init(argv[0]);
      
       signal_flag=1;      
      
       /*初始化进程id数组*/
       g_curr_fork=0;
       for(i=0;i<SYS_FORK_SIZE;i++)
       {
              g_chldpid[i]=-1;
       }
                       
       while(1)
       {                                                                                                         
              if(signal_flag==1)
               {/*只进行一次安装即可,还有在捕获信号后也进行一次重新的安装以避免不可靠信号又恢复为默认动作
                       注意这类信号处理函数要在安装后才可以用,如没安装是捕捉不到相应的信号的 */
                       signal(SIGCHLD,sig_chld);
                       signal(SIGTERM,sig_term);
                       signal_flag=0;
               }
              
              if( shut_flag==1 && g_curr_fork==0 )
                     {
                            break;
                     }
                                          
              if(g_curr_fork<G_FORK_MIN)
                     {                                          
         if( (ch_pid=fork())!=0 )/*注意是fork函数会返回两次*/
                      {                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                             /**************1***************/
                             for(i=0;i<SYS_FORK_SIZE;i++)
                   {
                           if( g_chldpid[i]==-1 )
                                  {
                                         g_chldpid[i]=ch_pid;
                                         g_curr_fork++;
                                         printf("ch_pid[%d],g_curr_fork[%d]\n",ch_pid,g_curr_fork);
                                         break;
                                  }
                   }                                                                                    
                      }else
                       {                        
                         break;
                       }                                                                                                                                 
           }
                                                                                                                                                     
              printf("in father!!!\n");
              sleep(5);                                                
       }/*while(1)*/
      
       if( shut_flag==1 )
              {
                     printf("the programme will exit!\n");
                     exit(0);
              }
                           
       /*only child can reach here*/      
       while(1)
       {
              signal(SIGTERM,sig_term_ch);
              
              pid=0;
              pid=getpid();
              printf("in chld[%d]...\n",pid);
              sleep(5);
       }
      
}




[size=5]问题就是有关子进程中如果不明确捕获SIGCHLD信号时,即注释掉signal(SIGTERM,sig_term_ch);这句的话,在程序运行稳定后(最终会生成5个子进程),用kill杀掉一个子进程,而在程序中还会继续收到由于杀死子进程而发出的SIGTERM信号.是不是因为安装SIGTERM信号的位置不对,比如放到上面程序的位置1,但是结果还是会这样.
我原本的想法是,kill子进程时,子进程不捕获SIGTERM信号这样子进程就会死掉而产生SUICHLD信号给父进程而再做相应的处理,但是现在却会捕获到SIGTERM信号,感觉到很迷惑,希望大家能不吝赐教!!!!![/size]

[[i] 本帖最后由 cy0space 于 2007-9-25 10:57 编辑 [/i]]

页: [1]
查看完整版本: UNIX下信号问题


Powered by Discuz! Archiver 5.5.0  © 2001-2006 Comsenz Inc.