Monday, 18 June 2012

Session, Foreground processes, Background processes, and their interaction with Controlling Terminal.

For more info visit

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 SIGTTOU 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.

Note: Make sure you run the following command, before executing above program.

stty tostop

This command stop the background jobs that try to write to the terminal.

No comments:

Post a Comment