Session: A session is a collection of process groups. In a session there can be only one foreground process group and more than one background process groups. The process which starts the session is known as session leader. A session leader can either be in a foreground process group or in a background process group.
Run the following command in your terminal to get the idea
ps -o pid,ppid,pgid,sid,tpgid,comm
The output will be similar as following
PID PPID PGID SID TPGID COMMAND 17335 17334 17335 17335 17495 bash 17495 17335 17495 17335 17495 ps
The column SID gives us the information about the session leader for the session. The SID will always be the process group id of the session leader, or we can also say that it will be same as id of session leader. Why?
Because whenever a new session is started, there is only a single process in the session, which is also known as session leader. This session leader is the process which starts the session.
In the above case, the session leader process is shell. We can also start our own sessions. Sessions are not started from some new process, but they are started from the currently existing process. The existing process is in some session before starting a new session. So, whenever a new session is started, the process which starts the new session is transferred to a new process group with group id same as its process id, means that the session starter process becomes the group leader of the new group. This new session contains only a single process, which is the starter process, and a single group in it.
As I said, a session leader can either be in foreground process group or background process group. In the above case, the shell, which is the session leader, is in background process group
Now, run the same command in background.
ps -o pid,ppid,pgid,sid,tpgid,comm &
The output will be
PID PPID PGID SID TPGID COMMAND
17601 17600 17601 17601 17601 bash 17610 17601 17610 17601 17601 ps
Now, in this case, the shell is in foreground process group. How do we get to know, which is foreground process group and which is background process group?
Here comes the concept of Controlling terminal
A controlling terminal is the terminal device which is connected to a session. A session can have only one terminal controller. The session leader, which makes the connection with the controlling process, is called Controlling Process. The Controlling terminal can only interact with the foreground process group.
The TPGID visible in the above example is Terminal process Group id, which is nothing, but the process group id of the foreground group process leader, which in second case is the shell.
The interrupts from the terminal such as ^C, ^D, etc are only going to effect the processes in the foreground process group.
Any Background process group can always be brought Foreground, provided the Background process group is in the same session as Foreground process group.
Now, let's see a simple example of toggling between Foreground process group and Background process group
#include<stdio.h>
#include<stdlib.h>
int main()
{
int pid;
pid=fork();
if(pid==0)
{
setpgid(getpid(),getpid());
sleep(2);
printf("\nin child process");
printf("\nchildpid %d",getpid());
printf("\nchildgrpid %d\n",getpgrp());
printf("\nchild done");
printf("\nchanged fpgid to child process%d\n",tcgetpgrp(1));
}
else
{
printf("\ninitial fpgid %d\n",tcgetpgrp(1));
printf("\nin parent process");
printf("\nparentpid %d",getpid());
printf("\nparentgrpid %d\n",getpgrp());
tcsetpgrp(1,pid);
wait();
printf("\nparent done");
printf("\nchanged fpgid to parent process%d\n",tcgetpgrp(1));
}
exit(0);
Compile and run the above program The output will be -
initial fpgid 17737
in parent process parentpid 17737 parentgrpid 17737
in child process childpid 17738 childgrpid 17738
child done changed fpgid to child process17738
[1]+ Stopped ./a.out
Now, let's analyse the program from beginning.
We fork() a child process and change its group id to its pid. Why? This is just to transfer the child process in some other group, as, after forking it would have inherited the group of its parent. We make it sleep for 2 secs, in order to run the parent process first.
In parent process, the parent's pid, pgid, and Foreground process group id is printed. Initially, the fpgid is same as parentgrpid. After printing all this, we change the fpgid to childgrpid or childpid. Parent process waits for child process to terminate.
Child process starts after 2 secs. It prints childpid, childgrpid and changed fpgid which now is same as childgrpid. This means, now child process group is the foreground process group. Child process prints "child done" and terminates.
Now what is this "[1]+ Stopped ./a.out".
Looks like some process has been stopped in the background. After seeing, we get to know that parent process has been stopped.
Why was it stopped?
It was stopped because it received signal SIGTOUT while trying to print the last two statements on the terminal. This terminal sends this signal to any background process group which tries to print something on terminal.
Since the parent process is not allowed to continue, the child process has also become ZOMBIE. Though the parent process has received the exit status of child process, it couldn't delete its details from process structure table.
Now we will start this stopped parent process by bringing it in foreground.
fg %1
The output will be
parent done changed fpgid to parent process17737
One more thing, just now we changed the fpgid to child process's group id. How did it revert back to parent process's group id.
It's simple, because when we brought the job with job id 1 to Foreground, all the processes of the group came to foreground.
No comments:
Post a Comment