Tuesday, 31 July 2012

fork() vs vfork().

For more info visitvfork() is same as fork(), it also creates a new process when it is called. The only difference is that, it doesn't copy the address space of parent into the address space of child. The main intention of using vfork() is that, child will run a new program using exec as soon as it is created, and so, shall not need a reference to the parent's address space.

After the child process is created, it runs on parent's address space until exec or exit is called. This means, both child and parent share the same address space until exec or exit is called.

vfork() also guarantees that after forking, child will be the first one to run until exec or exit is called. While the child process is running, before calling exec or exit, parent process will not run. Parent process will resume only when exec or exit is called by the child process.

Below given is a simple example, which will help you to understand the difference between them.

Compile and execute the following program

 
#include<stdio.h>
#include<stdlib.h>
int main()
{
int pid,var=1;
if((pid=vfork())==0)
{
// Child process starts
var=var+1;
exit(0);
// Child process ends
}
// Parent process continues
printf("value of var %d",var);
return 0;
}


Note the value of var. The output will be

value of var 2.

As we can see, the value of var in parent's address space has been changed by the child process. This means, no other address space was created for child, unless exec was called.

Now run the same program using fork() instead of vfork(), and the output will be

value of var 1.

This is because, we are changing var in child's address space, so value in parent's address space will not change.

 

Monday, 16 July 2012

Records in PL/SQL.

For more info visit

A record, as the name signifies, is a collection of more than one fields in a variable. For those of you who are familiar with language "C", you can compare a record to a structure in "C". The fields of a record can be of sql  or pl/sql type.

There are two ways in which a record can be declared.

1) Using Anchor Declarations(Table Based or Cursor Based Records).

ex:   employee_details employee%ROWTYPE;

Here employee is a table . Suppose, employee table has structure as shown below.

 EMP_ID                                             NOT NULL                 NUMBER
 EMP_NAME                                    NOT NULL                 VARCHAR2(10)

 We can collect the values corresponding to some row of a table in the record as

SELECT * into employee_details FROM employee WHERE emp_id  = 1;

and after that, we can access or manipulate the fields in the record using ".".

employee_details.emp_name

In the same way, we can also declare a record of Cursor type

CURSOR employee_cursor is SELECT * into employee_details FROM employee WHERE emp_id  = 1;

emp_cur employee_cursor%ROWTYPE;

We can directly fetch values from cursor into our record as

OPEN employee_cursor;

FETCH employee_cursor INTO emp_cur;

2) Programmer Defined Records:

In a programmer defined records, we can decide the field of our records. It doesn't have to be dependent on any table or cursor for its structure. These type of records are declared as

TYPE emp_rec IS RECORD

( name employee.emp_name%TYPE,

age NUMBER(3),

salary NUMBER(10) := 0

);

employee_record emp_rec;

In this type of record, we are free to define our own fields with different datatypes. We can always specify [NOT NULL]:=[DEFAULT] with the fields of a record. These types of records are useful when we want to collect data from different tables or when our record has nothing to do with tables or cursors.

We can manipulate the fields of these type of records in a number of ways, for example

employee_record.name := 'John';

select name into employee_record.name from employee where emp_id = 1;

 Note:

1) Two records cannot be compared as rec1=rec2, even if they are of same record type. Comparision of two records can only be done on field basis.

2) Values of a record can be assigned to other record if they are of same record type.

rec1 := rec2;

3) Records can be passed as parameters or can be returned from a function.

4) IS NULL cannot be used to check if all the fields of a record are NULL.

5) NULL can be assigned to a record as

rec1 := NULL;

6) We can insert the whole record into a table(without using individual fields), only if the record is declared using anchored declaration.

emp_rec employee%ROWTYPE;

insert into employee values emp_rec;

Sunday, 8 July 2012

Difference between dup() and dup2().

For more info visitdup() and dup2() are system calls which are used to duplicate file descriptors. Each process has a file descriptor table which contains the pointers to the file tables, process is using.

File descriptors are generally indexes of that table. The real information, i.e. the File pointer, is stored corresponding to these indexes. File pointer points to the file table which contains various attributes of files, such as current offset of file, file status flag, v-node information etc. Whenever a process forks, i.e creates a new child process, all the information in this table is copied to the child process's memory space.

While the information is copied from parent to child process, file pointer information from file descriptor table is also copied, so both the file pointers in both the memory spaces(child as well as Parent) point to the same File table. All the attributes in the File table( for the copied file pointers) are common for both, child as well as Parent.

This was the brief description about how the files descriptors work in the process. For detail information about file descriptors visit.

Now, as told earlier, dup() and dup2() are system calls which are used to duplicate file descriptors. By duplicating file descriptors we mean, the pointer information is copied from one location of the descriptor table to other location, no new file table is made for this process, only the file table is pointed by one more location in the descriptor table.

dup() : dup(int filedes) takes a file descriptor as its argument and duplicates the next lowest available file descriptor with the same file table pointer. It returns the new file descriptor value.

Suppose in a process, we want to duplicate the output file descriptor (1). Call

dup(1)

which will return the next lowest available file descriptor. If the process has

0 as the input descriptor

1 as output descriptor

2 as error output descriptor.

then calling the dup() will return 3 as the next available file descriptor, which will point to the terminal(same as 1).

dup2() : Using dup(), we are never sure about the value which will be returned. It will automatically return the next lowest available file descriptor. In some cases, we may need to duplicate a file descriptor as another file descriptor, we use dup2().

dup2(int filedes1, int filedes2) takes two file descriptors as its arguments. Let's suppose, we want to duplicate file descriptor 5 with file descriptor 1, i.e we want the file descriptor 5 to point at the same file table as file descriptor 1.

We will call dup2(1,5). It first checks, if file descriptor 5 is already open. If it's open, it closes the file descriptor 5 and opens it again, with the pointer pointing to the same file table, in the same way as 1.

If file descriptor 5 was already pointing to that table, it returns -1.

One more thing, we could have implemented the same functionality as below.

close(filedes2)

dup(filedes1)

But we don't do it like this. Why?

If we see, the above two operations are not atomic, i.e. we have a slight open time window between call to close and call to dup, so there is a possibility of some signal handler function(in case we receive a signal between these two calls) to alter the pattern of file descriptors. 

Generally, we use these duplicate system calls in case of Inter Process Communication, where we make pipes for the communication between two processes.

Monday, 2 July 2012

Oracle WITH Clause.

For more info visit

WITH clause is also known as Subquery factoring clause. It is used to simplify the structure of complex queries, and in some cases, optimize the queries.

With clause works in the same way as a Temporary table or an inline view, but the main difference between With clause and, an inline view or a Temporary table is that, a query written using With clause is less complex and easier to understand.

When we use a With clause, it depends on the optimizer whether it will make temporary table or an inline view, corresponding to the subquery in the With clause. This also depends on the subqueries used in With clause, if the queries are too complex then the optimizer may create Temporary tables ,else an inline view is sufficient.

We can also pass Optimizer hints in the subqueries written in with clause, to request the optimizer for an inline view or a Temporary table.

Select /*+ MATERIALIZE */ .... For Temporary table

Select /*+ INLINE */ ..... For Inline view

Now let's see an example, with and without With clause.

Suppose I want to find out the names of the employees having salary greater than the average salary of the department in which they work.

I can write this query in 3 ways.

1) Using Corelated Subqueries.

select ed1.name from employee_details ed1
where salary>(select avg(salary) from
employee_details ed2 where
ed1.department=ed2.department)

Writing corelated subquery is fine when data in the tables is less, but when there is a large amount of data in tables then this approach may not be suitable. For each employee in the table, the subquery will execute. So, we discard this approach in case of huge amount of data in tables.

2) The second approach is to create Inline view.

select ed1.name from employee_details ed1,
(Select avg(salary) sal,department
from employee_details group by
department) ed2 where ed2.department=ed1.department
and ed1.salary > ed2.sal

Here, an inline view is created, which is more efficient in case of huge amount of data. The query given above contains only one inline view, but what about the queries containing many inline views. It will become very complex to understand.

3) Using With Clause.

There is not much difference between aWith clause and an inline view, except the way of writing queries becomes more understandable.

Now, let's see the same query using a With Clause.

With ed2 as(Select avg(salary) sal,department
from employee_details group by
department)
select ed1.name from employee_details ed1,
ed2
where ed1.department=ed2.department and
ed1.salary>ed2.sal

The queries using With clause starts with With instead of Select, which may seem wierd at first, but as you start using With Clause, it will become inseparable part of  writing simple and understandable queries.

With clause may come handy in a lot of other situations(demanding subqueries), the only limit is how efficiently we can reduce the complexity of our queries using With Clause.

Saturday, 30 June 2012

sigsuspend vs pause...

For more info visit

sigsuspend and pause, both do the same work, they pause or temporarily stops the process until they receive some signal. These functions return, once the signal handling of the signal is complete.

A small difference between these functions is that, in sigsuspend, we can specify the signal mask to which the function should not listen. Suppose we implement the sigsuspend in the following manner

sigset_t tempmask; sigemptyset(&tempmask); sigaddset(&tempmask,SIGINT); sigsuspend(&tempmask);

Now, in the above code, we have specified the sigsuspend function to listen for every signal except SIGINT.

When sigsuspend receives any other signal than SIGINT, it returns.

This was a small difference between sigsuspend and pause. We get to know the major difference between their ways of working, when we have a scenario, and we try to implement it by both.

Suppose my scenario is, I have a program with two critical regions. By critical regions, I mean to say that I don't want some signal to interrupt in between, while my critical section is executing. But, at the same time I want my second critical section to start, only if I get the confirmation, that some signal has been received.

This is a very natural scenario, and we may encounter this type of condition anytime in our programs. Suppose I have two processes, p1 and p2, p2 has two critical sections, and it wants to go ahead with its second critical section only if it receives, a signal from p1 or has already received a signal from p1, and at the same time it doesn't want the signal to disturb, during the execution of its critical sections.

Let's see, how we can implement this scenario using pause()

#include<stdio.h> #include<signal.h> static void rec(int signo) { printf("\ninterrupt received\n"); } int main() { sigset_t mask1,mask2; signal(SIGINT, rec); sigemptyset(&mask1); sigaddset(&mask1,SIGINT); sigprocmask(SIG_BLOCK,&mask1,&mask2); printf("\ncritical region 1\n"); sleep(5); printf("\ncritical region 1 ends\n"); sigprocmask(SIG_SETMASK,&mask2,NULL); pause(); sigprocmask(SIG_BLOCK,&mask1,&mask2); printf("\ncritical region 2\n"); sleep(5); printf("\ncritical region 2 ends\n"); sigprocmask(SIG_SETMASK,&mask2,NULL); exit(0); }

We are using only one process, and let's assume that SIGINT is the signal which should not be allowed to interrupt the process during execution of critical section. In the above program, we block SIGINT before starting of any critical section and unblock it when the criticel section is over.

The program also pauses for confirmation that SIGINT is received before proceeding towards second critical section.

We unblock the signal SIGINT once the critical section ends, in order to receive the SIGINT signal. The main problem with this program is that, there is a time window, between unblocking of signal and pause, in which the signal can be received. In this case, the process will go to an infinite pause.

To test this problem, send the SIGINT from the terminal before the critical section 1 ends, i.e. when the process is in sleep inside first critical section

sigprocmask(SIG_SETMASK,&mask2,NULL);

//window in which the signal could be received pause();

To solve this problem, we make use of sigsuspend. We will write another program implementing the same logic, but using sigsuspend.

#include<stdio.h> #include<signal.h> static void rec(int signo) { printf("\ninterrupt received\n"); } int main() { sigset_t mask1,mask2; signal(SIGINT, rec); sigemptyset(&mask1); sigaddset(&mask1,SIGINT); sigprocmask(SIG_BLOCK,&mask1,&mask2); printf("\ncritical region 1\n"); sleep(5); printf("\ncritical region 1 ends\n"); sigsuspend(&mask2); printf("\ncritical region 2\n"); sleep(5); printf("\ncritical region 2 ends\n"); sigprocmask(SIG_SETMASK,&mask2,NULL); exit(0); }

The above program is not unblocking the SIGINT to receive it. Infact, it is using sigsuspend in place of it.

We are passing original process mask, which doesn't mask SIGINT,  in sigsuspend function. sigsuspend pauses the process and can only return if any of the signal, which is not in mask2, is received and its signal handler is executed. So, sigsuspend will return upon receival of SIGINT . When sigsuspend returns it resets the sigmask for the process to the mask just before when sigsuspend executed. In this case the SIGINT will be blocked again before execution of second critical section starts.

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.

Sunday, 10 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 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.