1. ホーム
  2. c

[解決済み] setpgid() による子プロセスのグループ化

2022-02-14 14:45:37

質問

全体がわからないんです。

私のプロセスツリー

     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() は、"No such process" または "Operation not permitted" のいずれかを返します。

pidはファイルに保存されているので setpgid()

どのように解決するのですか?

あるプロセスでは、プロセスグループIDを のみ、またはその子である . さらに、子プロセスがexec関数のいずれかを呼び出した後は、その子プロセスのプロセスグループIDを変更することができません。 --APUE

私見ですが

1.祖父母はそのgradechildでsetgpid()を使用することはできません。

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

2.setgpid()で変更できるのは、自分とその子供のpgidのみです。pid 3とpid 5は親子ではないので、pid 3にsetpgid(pid5, pid3)とは書けないのです。

だから、setgpid(誰かの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