I just don’t get the whole thing.
My process tree:
0 / 1 2 / 5 3 / 4
I want to make a process group (3, 4, 5), and send this group a signal from, say, 2.
I tried it this way:
setpgid(pid3, pid3); setpgid(pid4, pid3); setpgid(pid5, pid3); ... kill(-pid3, SIGUSR1);
Where should I place my setpgid()
block? I tried placing it in 3, 0 and every other process, but setpgid()
s return either “No such process” or “Operation not permitted”.
pids are stored in files, so I retrieve them just before calling setpgid()
Advertisement
Answer
A process can set the process group ID of only itself or any of its children. Furthermore, it can’t change the process group ID of one of its children after that child has called one of the exec functions. –APUE
In my opinion,
1.a grandparent can’t use setgpid() with its gradechild, you can check this easily.That’s to say, the code in pid 0 below won’t work:
setpgid(pid3, pid3); setpgid(pid4, pid3); setpgid(pid5, pid3);
2.you can only use setgpid() to change one’s and itselves chilld pgid,you can’t write down setpgid(pid5, pid3) in pid 3, because pid 3 and pid 5 aren’t parent and child.
So, you’d better use setgpid(someone’s pid, pgid) in itself.
But how can one process know other processes’ pid? A method is shared memory.
Here is one rough but a litte complex implement I just wrote, which don’t consider process synchronization.It works as you expected.
#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:%sna", 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:%dn",i,pid[i]); kill(-pid[3],SIGUSR1); } } void sig_usr3(int signo) { if(signo == SIGUSR1) printf("recieved sigal in process 3npid is %dnn",getpid()); exit(0); } void sig_usr4(int signo) { if(signo == SIGUSR1) printf("recieved sigal in process 4npid is %dnn",getpid()); exit(0); } void sig_usr5(int signo) { if(signo == SIGUSR1) printf("recieved sigal in process 5npid is %dnn",getpid()); exit(0); }
output:
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