トップ 一覧 検索 ヘルプ RSS ログイン

match.cの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!!match.c
*2つの対戦プログラムをそれぞれ子プロセスとして起動.
*子プロセスは賭金を標準出力に書き出すので,それをパイプから読み出す.
*相手の賭金をパイプに書き出す.子プロセスはそれを標準入力から読む.
*システムコールdup2を用いてパイプと標準入出力の入れ替えを行っている.
*子プロセスが異常終了したり,ハングアップしたときのために,シグナルを受け取ったら,子プロセスをkillする.
*これをしないと,子プロセスがゾンビとなって永久に動き続ける.

 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <signal.h>
 
 #define BUFSIZE 256
 
 int sum1=0,sum2=0;
 int point1=0,point2=0;
 int p_to_c1[2],c1_to_p[2];
 int p_to_c2[2],c2_to_p[2];
 char buf[BUFSIZE];
 int win1=0,win2=0;
 int pid1=-1,pid2=-1;
 
 void exit_program(int code){
   if(pid1>=0)
     kill(pid1,SIGKILL);
   if(pid2>=0)
     kill(pid2,SIGKILL);
   exit(code);
 }
 
 void sig_receive(){
   exit_program(EXIT_FAILURE);
 }
 
 void write_int(int fd, int n){
   snprintf(buf,BUFSIZE,"%d\n",n);
   write(fd,buf,strlen(buf));
   fsync(fd);
 }
 
 int read_int(int fd){
   int i;
   for(i=0;i<BUFSIZE;++i){
     read(fd,buf+i,1);
     if(buf[i]=='\n'){
       buf[i]=0;
       break;
     }
   }
   return(atoi(buf));
 }
 
 int main(int argc,char **argv){
   int i,j;
   int num_game;
 
   if(argc<=3){
     fprintf(stderr,"Usage: match program1 program2 num_game\n");
     exit(EXIT_SUCCESS);
   }
   
   num_game = atoi(argv[3]);
   if(num_game <= 0){
     fprintf(stderr,"num_game must be more than 0\n");
     exit(EXIT_FAILURE);
   }
   
   pipe(p_to_c1);
   pipe(c1_to_p);
   pipe(p_to_c2);
   pipe(c2_to_p);
 
   if((pid1=fork())==0){  // child1
     close(p_to_c1[1]);
     close(c1_to_p[0]);
     dup2(p_to_c1[0],0);
     dup2(c1_to_p[1],1);
     execl(argv[1],argv[1],argv[3],NULL);
     fprintf(stderr,"Cannot execute %s\n",argv[1]);
     exit_program(EXIT_FAILURE);
   }
 
   if((pid2=fork())==0){  // child2
     close(p_to_c2[1]);
     close(c2_to_p[0]);
     dup2(p_to_c2[0],0);
     dup2(c2_to_p[1],1);
     execl(argv[2],argv[2],argv[3],NULL);
     fprintf(stderr,"Cannot execute %s\n",argv[2]);
     exit_program(EXIT_FAILURE);
   }
 
   signal(SIGHUP,sig_receive);
   signal(SIGINT,sig_receive);
   
   printf("%s vs %s\n",argv[1],argv[2]);
 
   for(j=1;j<=num_game;++j){
     sum1=0;
     sum2=0;
     point1=0;
     point2=0;
     
     printf("------------------------------------\n");
     printf("game %d\n",j);
     for(i=1;i<=10;++i){
       int bet1,bet2;
       bet1=read_int(c1_to_p[0]);
       bet2=read_int(c2_to_p[0]);
       sum1+=bet1;
       sum2+=bet2;
 
       if(bet1<bet2){
         point1+=bet1+bet2;
         printf("%2d: [%4d]  %4d  -> %5d %5d\n",i,bet1,bet2,point1,point2);
       } else if(bet1>bet2){
         point2+=bet1+bet2;
         printf("%2d:  %4d  [%4d] -> %5d %5d\n",i,bet1,bet2,point1,point2);
       } else {
        point1+=bet1;
        point2+=bet2;
         printf("%2d:  %4d   %4d  -> %5d %5d\n",i,bet1,bet2,point1,point2);
       }
 
       if(bet1<0){
         printf("%2d: %s bet %d.\n",i,argv[1],bet1);
         exit_program(EXIT_FAILURE);
       }
       if(bet2<0){
         printf("%2d: %s bet %d.\n",i,argv[2],bet2);
        exit_program(EXIT_FAILURE);
       }
 
       write_int(p_to_c1[1],bet2);
       write_int(p_to_c2[1],bet1);
     }
 
     if(sum1!=10000){
       printf("%s bet totally %d.\n",argv[1],sum1);
       exit_program(EXIT_FAILURE);
     }
     if(sum2!=10000){
       printf("%s bet totally %d.\n",argv[2],sum2);
       exit_program(EXIT_FAILURE);
     }
     if(point1>point2){
       printf("  [%5d]  %5d\n",point1,point2);
       printf("%s won.\n",argv[1]);
       win1++;
     } else if(point1<point2){
       printf("   %5d  [%5d]\n",point1,point2);
       printf("%s won.\n",argv[2]);
       win2++;
     } else {
       printf("   %5d   %5d\n",point1,point2);
       printf("Draw.\n");
     }
   }
   printf("------------------------------------\n");
   printf("%s won : %d, %s won : %d, Draw : %d\n",argv[1], win1, argv[2], win2, num_game-win1-win2);
   exit_program(EXIT_SUCCESS);
   exit(0);
 }