2013-05-19 63 views
3

我只是不明白整個事情。用setgpid()分組子進程

我的進程樹:

 0 
    /\ 
    1 2 
/ \ 
5  3 
     /
     4 

我想打一個進程組(3,4,5),併發送這一組,比如說一個信號,2

我試了一下這個方法:

setpgid(pid3, pid3); 
setpgid(pid4, pid3); 
setpgid(pid5, pid3); 

... 

kill(-pid3, SIGUSR1); 

我應該在哪裏把我setpgid()塊?我嘗試將它放在3,0和其他所有進程中,但setpgid()返回「沒有這樣的進程」或「操作不允許」。

PID都被存儲在文件中,所以我找回它們只是調用setpgid()

回答

3

進程可以設置進程組ID之前只有本身或任何其子的。此外,在子進程調用其中一個exec函數後,它不能更改其子進程的組進程ID。 --APUE

在我看來,

1.A祖父母不能使用其gradechild setgpid(),您可以檢查此easily.That的說,在PID 0下面的代碼將無法正常工作:

setpgid(pid3, pid3); 
setpgid(pid4, pid3); 
setpgid(pid5, pid3); 

2.you只能使用setgpid()來改變一個人的和itselves chilld PGID,你不能寫在PID 3 setpgid(PID5,PID3),因爲PID 3和pid 5不是父母和孩子。

所以,你最好使用setgpid(someone's pid,pgid)本身。

但是,一個進程如何知道其他進程的PID?一種方法是共享內存。

這裏是一個粗糙而複雜的實現,我剛纔寫道,它不考慮進程同步。它按預期工作。

#include "stdlib.h" 
#include "stdio.h" 
#include "errno.h" 
#include "unistd.h" 
#include "string.h" 
#include "sys/stat.h" 
#include "sys/types.h" 
#include "sys/ipc.h" 
#include "sys/shm.h" 
#include "signal.h" 
#define PERM S_IRUSR|S_IWUSR 

void sig_usr3(int); 
void sig_usr4(int); 
void sig_usr5(int); 

int main() { 
    size_t msize; 
    key_t shmid; 
    pid_t *pid; 
    msize = 6 * sizeof(pid_t); 
    if((shmid = shmget(IPC_PRIVATE, msize , PERM)) == -1) { 
     fprintf(stderr, "Share Memory Error:%s\n\a", strerror(errno)); 
     exit(1); 
    } 
    pid = shmat(shmid, 0, 0); 
    memset(pid,0,msize); 
    pid[0] = getpid(); 
    //process 0 
    if(fork() == 0) { 
    //process 1 
     pid = shmat(shmid, 0, 0); 
     pid[1] = getpid(); 
     if(fork() == 0) { 
      //process 5 
      pid = shmat(shmid, 0, 0); 
      pid[5] = getpid(); 
      while(pid[3]==0) 
       sleep(1); 
      if((setpgid(pid[5],pid[3]))==-1) 
       printf("pid5 setpgid error.\n"); 
      signal(SIGUSR1,sig_usr5); 
      for(;;) 
       pause(); 
     } 
     for(;;) 
      pause(); 
     exit(0); 
     } 

    if(fork() == 0) { 
     //process 2 
     pid = shmat(shmid, 0, 0); 
     pid[2] = getpid(); 
     if(fork() == 0) { 
      //process 3 
      pid = shmat(shmid, 0, 0); 
      pid[3] = getpid(); 
      if((setpgid(pid[3],pid[3]))==-1) 
       printf("pid3 setpgid error.\n"); 
      if(fork() == 0) { 
       //process 4 
       pid = shmat(shmid, 0, 0); 
       pid[4] = getpid(); 
       if((setpgid(pid[4],pid[3]))==-1) 
        printf("pid4 setpgid error.\n"); 
       signal(SIGUSR1,sig_usr4); 
       for(;;) 
        pause(); 
      } 
      else { 
       signal(SIGUSR1,sig_usr3); 
       for(;;) 
        pause(); 
      } 
      for(;;) 
       sleep(100); 
    } 

    if(getpid()==pid[0]) { 
     int i,flag; 
     while(!(pid[0]&&pid[1]&&pid[2]&&pid[3]&&pid[4]&&pid[5])) 
      //wait for all process folking. 
      sleep(1); 

     for(i=0;i<6;i++) 
      printf("process %d,pid:%d\n",i,pid[i]); 
     kill(-pid[3],SIGUSR1); 
    } 
} 

void sig_usr3(int signo) { 
    if(signo == SIGUSR1) 
     printf("recieved sigal in process 3\npid is %d\n\n",getpid()); 
    exit(0); 
} 

void sig_usr4(int signo) { 
    if(signo == SIGUSR1) 
     printf("recieved sigal in process 4\npid is %d\n\n",getpid()); 
    exit(0); 
} 

void sig_usr5(int signo) { 
    if(signo == SIGUSR1) 
     printf("recieved sigal in process 5\npid is %d\n\n",getpid()); 
    exit(0); 
} 

輸出:

process 0,pid:31361 
process 1,pid:31362 
process 2,pid:31363 
process 3,pid:31364 
process 4,pid:31366 
process 5,pid:31365 
recieved sigal in process 3 
pid is 31364 

recieved sigal in process 5 
pid is 31365 

recieved sigal in process 4 
pid is 31366 
+0

謝謝你的很好的例子。當我意識到我不需要任何進程同步,也不需要共享內存技巧時,事情變得更加容易。我在3和4中用'setpgid(getpid(),getpgid(getppid()))'創建了一個組(2,3,4)。這正是我所需要的。顯然,對於更復雜的任務,我會考慮你的解決方案。 –