天天看點

fork and exec

程式分歧fork() 

  fork()會産生一個與父程式相同的子程式,唯一不同之處在於其process 

  id(pid)。  

  如果我們要撰寫守護神程式,或是例如網路伺服器,需要多個行程來同時提供 

  多個連線,可以利用fork()來産生多個相同的行程。  

  函數宣告 

  pid_t fork(void);  

  pid_t vfork(void);  

  傳回值: 

  -1 : 失敗。  

    0 : 子程式。  

  >0 : 将子程式的process id傳回給父程式。  

  在Linux下fork()及vfork()是相同的東西。  

  範例一: fork.c 

  在這個範例中,我們示範fork()的标準用法。  

  #include <stdio.h>  

  #include <stdlib.h>  

  #include <unistd.h>  

  void main(void)  

  {  

    pid_t pid;  

    printf("hello/n");  

    pid = fork();  

    switch (pid) {  

      case -1: printf("failure!/n"); break;  

      case  0: printf("I am child!/n"); break;  

      default: printf("my child is %d/n",pid); break;  

    }  

    for (;;) {  }  

  }  

  編譯: 

  gcc -o ex1 fork.c  

  執行結果: 

  ./ex1 &  

  hello  

  my child is 8650  

  I am child!  

  我們可以見到,使用fork(),可将一個程式分岐成兩個。在分歧之前的程式碼 

  隻執行一次。  

  檢驗行程: 

  ps | grep ex1  

   8649  p0 R    0:40 ./ex1  

   8650  p0 R    0:40 ./ex1  

  8649是父程式的pid,8650則為子程式的pid。  

  您會需要用到"killall ex1"來殺掉兩個行程。  

  範例二: daemon.c 

  在UNIX中,我們一般都利用fork(),來實作所謂的"守護神程式",也就是DOS中 

  所謂的"常駐程式"。一般的技巧是将父程式結束,而子程式便成為"守護神"。  

  這個範例中,示範一般标準的daemon寫法。  

  #include <stdio.h>  

  #include <stdlib.h>  

  #include <unistd.h>  

  void main(void)  

  {  

    pid_t pid;  

    pid = fork();  

    if (pid>0) {  

      printf("daemon on duty!/n");  

      exit(0);  

    } else  

    if (pid<0) {  

      printf("Can't fork!/n");  

      exit(-1);  

    }  

    for (;;) {  

      printf("I am the daemon!/n");  

      sleep(3);  

    }  

  }  

  編譯: 

  gcc -o ex2 daemon.c  

  執行結果: 

  ./ex2  

  daemon on duty!  

  I am the daemon!  

  接下來每三秒鐘,都會出現一個"I am the daemon!"的訊息,這表示您的程式 

  已經"長駐"在系統中了。  

  檢驗行程: 

  ps | grep ex2  

  8753  p0 S    0:00 ./ex2  

  注意到在範例一中,我們下的指令為"./ex1 &",而在範例二中為"./ex2",沒 

  有"&"符号。  

  範例三:Perl Script

 my @subpid;

 my $rtpid = $$;

 foreach my $file (@file){

  chomp $file;

  my($file, $dir, $ext) = fileparse($file);

  if (1 == 1) {

   my $exec_cmd = "$cmp_cmd  ${rsyncTgtDir}${file} ${rsyncTmpDir}${file}";

   my $pid = fork();

   if ($pid == 0){

    setpgrp(0, $rtpid);

    exec($exec_cmd);

    print "fail to execute $exec_cmd/n";

    exit(1);

   }

   else{

    push(@subpid, $pid);

   }

  }

 }

 if($$ == $rtpid ){

  foreach my $pid (@subpid){

   if(getpgrp($pid) == $rtpid ){

    waitpid($pid, 0);

   }

  }

 }

繼續閱讀