【问题标题】:Grouping child processes with setpgid()使用 setpgid() 对子进程进行分组
【发布时间】:2013-05-19 20:40:26
【问题描述】:

我只是不明白整个事情。

我的进程树:

     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()s 返回“没有这样的进程”或“不允许操作”。

pid 存储在文件中,所以我在调用 setpgid() 之前检索它们

【问题讨论】:

    标签: c linux process


    【解决方案1】:

    一个进程可以只设置它自己或其任何子进程的进程组ID。此外,在该子进程调用其中一个 exec 函数后,它不能更改其子进程之一的进程组 ID。 --APUE

    在我看来,

    1.祖父母不能使用setgpid()和它的gradechild,你可以很容易地检查这个。也就是说,下面pid 0中的代码不起作用:

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

    2.你只能用setgpid()来改变自己的cold 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
    

    【讨论】:

    • 谢谢你的好例子。当我意识到我不需要任何进程同步或共享内存技巧时,事情变得容易多了。我在 3 和 4 中用setpgid(getpid(), getpgid(getppid())) 创建了一个组(2、3、4)。这正是我所需要的。显然,对于更复杂的任务,我会考虑您的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2011-09-14
    • 2015-09-12
    • 2010-11-13
    • 2021-12-21
    • 2020-04-11
    • 1970-01-01
    • 2021-05-19
    • 2021-05-04
    相关资源
    最近更新 更多