Sunday, September 28, 2014

Unix Prog: Process Groups

1. getpgrp, getpgid

system definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
 ......  
 /* Get the process group ID of the calling process. */  
 extern __pid_t getpgrp (void) __THROW;  
   
 /* Get the process group ID of process PID. */  
 extern __pid_t __getpgid (__pid_t __pid) __THROW;  
 ......  

for getpgid, if pid is 0, the calling process's id is used.
So getpgrp() = getpgid(0)

Example:
pg.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 int main(int argc, char* argv[])  
 {  
  printf("getpid: %d\n", getpid());  
  printf("getpgrp: %d\n", getpgrp());  
  printf("getpgid: %d\n", getpgid(0));  
  exit(0);  
 }  

shell:
the program outputs the process id, process group id.
In this case, process id is equal to process group id, which means this process is the leader of process group.
 ubuntu@ip-172-31-23-227:~$ ./pg.out  
 getpid: 12136  
 getpgrp: 12136  
 getpgid: 12136  

Process Group Life Cycle:
The process group will exist as long as there is more than 0 process in this group, even if the process is not the leader. The last remaining process in the group can choose to terminate the process group or join another process group.

2. setpgid

System Definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
 ......  
 /* Set the process group ID of the process matching PID to PGID.  
   If PID is zero, the current process's process group ID is set.  
   If PGID is zero, the process ID of the process is used. */  
 extern int setpgid (__pid_t __pid, __pid_t __pgid) __THROW;  
 ......  

A process can only change the process group of itself and any of its children process.

Example:
pg.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 int main(int argc, char* argv[])  
 {  
  pid_t pid;  
   
  printf("Parent Process Id: %d\n", getpid());  
  printf("Parent Process Group Id: %d\n", getpgrp());  
   
  if((pid = fork()) < 0) {  
   printf("fork error!\n");  
   exit(1);  
  }  
  else if(pid == 0) { // child process  
   printf("Child Process Id: %d\n", getpid());  
   printf("Child Process Group Id: %d\n", getpgrp());  
   sleep(3);  
   printf("After sleeping, child process group id: %d\n", getpgrp());  
   exit(0);  
  }  
   
  sleep(2);  
  printf("setup child process group to %d\n", pid);  
  if(setpgid(pid, pid) == -1) {  
   printf("setpgid error!\n");  
   exit(2);  
  }  
   
  exit(0);  
 }  

shell:
When launching the parent process, its id is 12216, and its group id is 12216 too. After "fork" another child process, the parent process start sleeping for 2 seconds. During this period, child process output is process id: 12217, process group id 12216, so child process is belonging to the parent process's group by default. After parent process wake up, it change child process's group to 12217, and after child process wake up, the operation prove to be successful.
 ubuntu@ip-172-31-23-227:~$ ./pg.out  
 Parent Process Id: 12216  
 Parent Process Group Id: 12216  
 Child Process Id: 12217  
 Child Process Group Id: 12216  
 setup child process group to 12217  
 ubuntu@ip-172-31-23-227:~$ After sleeping, child process group id: 12217  

Note: the child process is always assumed to be part of parent process group by default. This happened before any re-assignment of child process group in parent process or child process, to avoid race condition.

No comments:

Post a Comment