Monday, June 13, 2011

Comparison between Various IPC

Comparison of IPC
Pipes
Advantages
1) Simplest from of IPC
2) Can be used in shell
Disadvantages
1) Only for related process
2) No message boundary

FIFO
Disadvantages
- Data cannot be broadcasted to multiple receivers
- If there are multiple receivers there is not way to direct the data to particular user
- Cannot be used across network
- Less secure than pipe, since any process with valid access permission can access them
- Cannot store data
- No message boundaries. Data is treated as stream of bytes
Message Queues
Advantages
1) can broadcast data ????
2) can direct data
3) can store data
4) message boundaries
disadvantage
1) effective for small amount of data
2) very expensive for large data, as transferred through kernel buffer and double coping
3) each data transfer involves 2 data copy operations
4) a message queue cannot be reused, since once the message is taken from the queue , message is removed from message queue.
Shared memory
1) faster method than queues
2) does not require extra kernel buffer
3) safe, manipulated like other variables
Disadvantages
1) data can either read or written only. Append is not possible
2) race condition is possible so locking is required.


Good to read

System V IPC Vs POSIX IPC

System V is used from Old version of Unix system operating system. Posix (Portable Operating System Interface Unix) is meant to be new portable implementation of IPC. Posix is supposed to be thread safe. But still System V is used widely.


http://stackoverflow.com/questions/4582968/system-v-ipc-vs-posix-ipc

Monday, June 6, 2011

pipe correct it

-If we read from a pipe whose write end has been closed, read returns 0
-If we write to a pipe whose read end has been closed, the signal SIGPIPE is generated

FIFO

- “mknod” command is used to create the fifo, mkfifo command is not available for C program in many linux distributions

- Once created you can use same open, read as you do on normal files

- O_NONBLOCK will depict the blocking behavior of FIFO same as pipes

- Pipe buffer is defined by the constant PIPE_BUF in limits.h header. I checked for me its 4k

- As many process can write to the file some sort of atomicity is required for these operations.

Pipes

Pipes

- One way communication

- Create pipe with pipe() system call as
int p[2]
pipe(p)
p[1] is the write end and p[0] is the read end.

- Pipe has some buffer associated with it, that can be checked with “ulimit” command

- Pipe u can understand like FIFO, stream buffer, there is no message boundary, its like bucket with one tap at the end, you can pour from top and get from the bottom. How much you get from bottom is not controlled at all, the longer tap is opened the more you get.

- In pipe terminology you can write() anything and get by read(), whatever buffers you pass in write and read function calls is independent. Remember

- Pipes can be used only if process are related ie. Child and parent. You create the pipe then fork the child. Though the fork would create copy of file descriptor returned but all four of them would point to the same thing.

- If you read a pipe before anything is written, read call will wait something for to be written.

- You have written 10 bytes, you try to read 50 what will happen, it will only give 10 J.

- Pipes are meant for one way communication, what will happen if you try to write from both process, if will still work, But its logically incorrect and there are more than one reasons to close the unused end.

- Reasons to close the unused end
1) file descriptors are limited, don’t let them opened.

2) suppose you create something like below
if(fork()==0)//child, assume it runs first

{

//do nothing closing

}

Else//parent process

{

Read(p[0],buff,5)

}

This program will hang forever, the reason is simple, child as it runs exits immediately and hence its file descriptors also closes. Now comes the parent, here read call is made, at this juncture process will wait for something to be written to the pipe as write end of the parent pipe is not closed. And hence process will keep on waiting. Logical correction of the program is to close the write end. If you close the write end in the parent system will know that there is no one who can write to the pipe hence closes the program immediately.

- Suppose child dies immediately and in parent you close read end first, there after you have write statement, Now unix knows there is no one to read hence thinks fool does not have mind hence sends SIGPIPE signal, whose default action is to the pipe.

- If any of the write end is not closed and pipe is empty, read call will make the prog wait. But if you don’t want to wait on read. You can always configure the pipe read end as O_NDELAY
fcntl(p[0], F_SETFL,O_NDELAY). Now when instead of waiting at read call next statement will be executed.


Pipes drawbacks

- Can only be used on related process

- Not permanent, termination of the process leads to their termination

- Its more like files, have i-node number etc. But they are not files, they you can think as kernel buffer, having some kernel max buffer size limit. E.g. its about 4k in my system-


Few words about pipe implementation

- Each pipe implemented as file mounted on virtual file system “pipefs”.

- The normal process would inovle with pipe call would be like: Creates an inode

- Creates a file

- Associates the directory entry and the inode with it

- Creates 2 file * by opening it with O_RDONLY and O_WRONLY flags

- Installs the file *s in the file descriptor table of the process and generates 2 file descriptors (of type int)

- Returns the file descriptors in the fd[2] array.

- Naturally read, write call on file would use some sort of locking mechanism. To read write data

How FIFO is implemented

- Its fully same as pipe only difference being the it creates and installs the inode in global file system instead of pipefs which is kind of virtual and non persistent

- Mknod call is used to create the fifo, btw mknod is used to create many type files

About Buffer removal

- For each pipe/FIFO reader writer count is maintained, when ever you close the fd, the reader write count is decremented, when count reaches zero it get rid of pipe buffer and pipe object is destroyed.

- In case of FIFO don’t get rid of the node entry but get rid of the kernel buffer

Wednesday, February 16, 2011

Message Queue

Message queues can also be used as synchronization object also.
In these kind of cases there is no payload, some bodya will just wait on the messge queue.
When message is received thread/process can continue their work.

Same thing is persent in the J Jobs. Where other J need to wait for ther other modules to complete the activity only then you can mark the job as competed. In that case J would be waiting for the message. Other module like I will send the message, then we will mark the job as competed.

In pSOS we have two types of queue, first one is the one having 4 long words as playload, Most of the embedded system these are more then eough to do the work. As we work of the physical address in single process address space.

But pSOS also has one more queue which is like same as System V IPC queue.

IPC: Message Queues

System V IPC consist of
Message Queues, Semaphores, Shared memory
Message Queues
Before talking about the what Message queues are, just like to point out disadvante of the other IPC, FIFO (named pipes)
Diadvantages of FIFO
1) data cannot be broadcased to mutliple receivers.
2) Cannot store Data
3) No message boundaries, Data is treaded as stream of bytes.

How to use
1) Create a Unique identification number, ftok() function
key_t ftok(const char *filenme, int id)
2) Get the resource
xxxget(ket_t key, int xxflg)
this syntax is common for all the ipc resources (msg, shm, sem)
3) All system V resources are controled by xxxctl function
xxxctl(int xxxid, int cmd, struct xxxid_ds *buffer)
The command argument can be anyone of these
IPC_STAT =>copy the infro the info from kernel structure to the pointer buffer
IPC_SET => write the info pointer by buffer to the message data structure
IPC_RMID => remove the object

4)
int msgget(key,msglag)
msgflog = IPC_CREATE | 0777
this 0777 is the queue permisssion
Message structure and message sending
struct my_msgbuf {
long mtype,
char any_data_arr[354]
};
Here you must should note that this "mtype" is necessary and used while receving the message.
"any_data_arr" can be any filed or you can add any number of the data elements in this structure later.

5) Send the mssage
msgsnd(msgid, &my_msbug, sizeof(my_msgbuf)-sizeof(long), flag)

flag = 0 or IPC_NOWAIT

6) Recevie the message
msgrcv(msgid, &my_msbug, sizeof(my_msgbuf)-sizeof(long), flag)
flag values are as below
0 = recevie the next message
postive = get the next message, whose mtype is equal to the flag
-ve = retrive the message whose abosolute values is less then or equal to the given value

7) When every thing is done do
msgctl(msqid, IPC_RMID, NULL)

http://beej.us/guide/bgipc/

Sunday, February 6, 2011

Zombie Process

/*
Zombie Process
Zombie means undead. Funda here is very simple,
->when process exit, its return status is collected by its parent
->IN case of orphan prcess, when child exits the parent is in sleep state and will not collect the status of the child
->as child status is uncollected, it cannot be cleared from system table and its occupies some of the system resources
->So its bad house keeping, as zombie is taking one process id etc.

*/

#include
int main()
{
int pid;

if(0==fork())
{

printf("Child Process [%d] Parent [%d]\n",getpid(), getppid());
printf("\n Check process table \n");
}
else
{
/*Parent immediatly spleeps and after child finishes you can check
process talbe there would be child process with defunct
*/
sleep(20);
printf("\n Parent waking up \n");
printf("Parent Process [%d] Parent [%d]\n",getpid(), getppid());

}

return 0;


}

Orphan Process

/*
This program will tell about orphan process.
As of now i cannot think of any side effect of orphan process
only thing which possibly could be your ophan process eating the resources which idealy you dont want it to have

*/

#include
int main()
{
int pid;

if(0==fork())
{
printf("Child Process [%d] Parent [%d]\n",getpid(), getppid());
sleep(5);
printf("Child Process [%d] Parent [%d]\n",getpid(), getppid());
}
else
{
sleep(1);
printf("Parent Process [%d] Parent [%d]\n",getpid(), getppid());
printf("Parent Process [%d] Parent [%d]\n",getpid(), getppid());
sleep(2);
}

return 0;


}

./3_orphan
Child Process [7070] Parent [7069]
Parent Process [7069] Parent [6602]
Parent Process [7069] Parent [6602]
Child Process [7070] Parent [1]

Monday, January 31, 2011

1 Basic of Process

Program will tell about basic of the process in linux system


/*
This program explain about the basic process creation in the linux operating system
1) its obvious that statement after the fork are executed twice. once on the behalf of main program and second as child process


*/

#include
int main()
{
int pid;

printf("\nThis will be executed only once [%d] [%d]\n", getpid(), getppid());
fork();
printf("\nTHis will be executed twice\n", getpid(), getppid());

return 0;

}

Output :
This will be executed only once [4665] [4299]

THis will be executed twice [4666] [4665]

THis will be executed twice [4665] [4299]




/*
program will show some clever use of pid. In this way you can segregate the parent process and child process code
one more important point fork returns zero to the child process.
why it return zero is, the answer is its the kernel implemenation of the kernel code

http://fxr.watson.org/fxr/source/kern/kern_fork.c?v=FREEBSD8

he code is a bit confusing if you're not used to reading kernel code, but the inline comments give a pretty good hint as to what's going on.

The most interesting part of the source with an explicit answer to your question is at the very end of the fork() definition itself -

if (error == 0) {
td->td_retval[0] = p2->p_pid;
td->td_retval[1] = 0;
}

"td" apparently holds a list of the return values for different threads. I'm not sure exactly how this mechanism works (why there are not two separate "thread" structures). If error (returned from fork1, the "real" forking function) is 0 (no error), then take the "first" (parent) thread and set its return value to p2 (the new process)'s PID. If it's the "second" thread (in p2), then set the return value to 0.

There is one more thing you can notice, only pid is set to zero not all the local variable, which tells justifies the kernel things


*/


#include
int main()
{
int pid;
int temp;




pid = fork();
if(0 == pid)
{

printf("\n I am child process [%d] [%d]\n", getpid(), getppid());
printf("Temp and Pid [%d] [%d]", temp, pid) ;
}
else
{
printf("\n I am Parent process [%d] [%d]\n", getpid(), getppid());
printf(" Temp and Pid [%d] [%d]", temp, pid) ;
}

return 0;


}
Output:
I am child process [4885] [4884]

Temp and Pid [-1080938856] [0]
I am Parent process [4884] [3314]

Temp and Pid [-1080938856] [4885]