Pages

Wednesday, September 23, 2015

Named Pipe(FIFO) and Unnamed Pipe(Pipe) : Differences


Pipes are synchronized way of passing information between processes.

Differences:


                         Unnamed Pipe(PIPE)
                                    Named Pipe(FIFO)
 They are unidirectional.
 They can be bidirectional.
They can only be used by related processes (parent/child or child/child having the same parent.)
They can be used by any process (unrelated processes.)
They are opened at the time of creation only.
They are not open at the time of creation.
They exist as long as the file descriptors are open.
They exist as directory entries
They are created by using the function pipe().
They are created by using the function mkfifo().
Eg: int pipe(int fd[2])
fd[0] – descriptor used for reading
fd[1] – descriptor used for writing
Eg: int mkfifo(char *path, mode_t mode)

Sunday, September 13, 2015

Character devices and Block devices


There are two main types of devices under Linux systems, block devices and character devices.

Character Devices
                                  Block Devices
The devices that conveys data character by character between the device and the user program.
The devices that read/write data in fixed size blocks.
Eg: Mouse, Keyboard
Eg: USB, Hard Disk
No buffering is performed
Block devices are accessed through a buffer
The first character is ‘c’ in the output of ls -l
cd to /dev and run the command ls -l
The first character is ‘b’ in the output of ls -l
cd to /dev and run the command ls -l
 

Saturday, September 5, 2015

Understanding Recursion

Recursion is a method where the solution to the problem depends on solution to smaller instances of the same problem.

The most common example for recursion is factorial. Let us see this with an example.

#include <stdio.h>

int factorial(int n){
    int F;
    printf("I am calculating the factorial of %d: ",n);
    if(n==0)
        return 1;
   
    F = n*factorial(n-1);
    printf("The calculation of factorial is done for %d\n",F);
    return F;
}

int main(){
  int n,result;

  printf("Enter the number to calculate the factorial \n");
  scanf("%d",&n);

  result = factorial(n);
  printf("The factorial is %d \n",result);
}

Can you guess what will be the output of this program, how the print statements are printed ?

Let's assume the number for which the factorial is to be calculated is 5.

factorial function is called with value 5--> the first printf statement is printed-->.The recursive function is then called with the value 5.

The calculation of 5*factorial(4) is paused as it needs to calculate the factorial first ie factorial(4).

So, it goes to beginning of function and the second printf statement is then printed -->factorial is called again with value 4,

The calculation 4*factorial(3) is paused as factorial(3) needs to be calculated first.

So, it goes to beginning of function and the third printf statement is then printed -->factorial is called again with value 3,

The calculation 3*factorial(2) is paused as factorial(2) needs to be calculated first.

So, it goes to beginning of function and the fourth printf statement is then printed -->factorial is called again with value 2,

The calculation 2*factorial(1) is paused as factorial(1) needs to be calculated first.

So, it goes to beginning of function and the fifth printf statement is then printed -->factorial is called again with value 1,

The calculation 1*factorial(0) is paused as factorial(0) needs to be calculated first.

So, it goes to beginning of function and the sixth printf statement is then printed. At this point n=0 and the value 1 is returned to factorial(0).

Now the paused calculations take place as follows:

Since factorial(0) =1,
The fifth calculation:factorial(1) = 1*factorial(0) =1 and the print statement is printed with n=1
The fourth calculation:factorial(2) = 2* factorial(1)=2 and the print statement is printed with n=2
The third calculation:factorial(3) = 3*factorial(2) =6 and the print statement is printed with n=3
The second calculation:factorial(4) = 4*factorial(3) = 24 and the print statement is printed with n=4
The first calculation:factorial(5) = 5*factorial(4) =120 and the print statement is printed with n=5

Finally F =120 and the value is printed.

The final output looks like this:

Enter the number to calculate the factorial: 5
I am calculating the factorial of 5
I am calculating the factorial of 4
I am calculating the factorial of 3
I am calculating the factorial of 2
I am calculating the factorial of 1
I am calculating the factorial of 0
The calculation of factorial is done for 1
The calculation of factorial is done for 2
The calculation of factorial is done for 3
The calculation of factorial is done for 4
The calculation of factorial is done for 5
The factorial is 120


Saturday, August 29, 2015

C System Calls and FILE I/O library function

System calls are special types of functions available in some programming languages. They are used by programs to communicate directly with the operating system. The OS talks back to the program through the return value of the function. When a system call is made, the control is relinquished to the operating system to perform the system call and the program is blocked until the call has finished. We should always check the return value as this is the only method the operating system communicates with the program. All these functions are included under header file unistd.h, sys/stat.h and sys/types.h. The return value is an integer. Operation takes place on file descriptor.

There are more than 100 system calls implemented as a part of C library. A few of C system calls are:

1. close : This closes the file descriptor.
    Function Definition : int close(int fildes);
2. dup : It provides and alias for the provided file descriptor.
    Function Definition : int dup(int fildes);
3. dup2:  It provides and alias for the provided file descriptor and then deletes the old file descriptor.
    Function Definition : int dup2(int fildes);
4. fstat : It is used to determine information about a file based on its file descriptor.
    Function Definition : int dup(int fildes, struct stat *buf); The second parameter stores the data             about the file.
5. lseek : change the location of the read/write pointer of a file descriptor. The location can be set           either in absolute or relative terms.
    Function Definition: off_t lseek(int fildes, off_t offset, int whence);
    whence :The method in which the offset is to be interpreted (relative, absolute, etc.).
 
ValueMeaning
SEEK_SETOffset is to be measured in absolute terms.
SEEK_CUROffset is to be measured relative to the current location of the pointer.
SEEK_ENDOffset is to be measured relative to the end of the file.
6. lstat :  determine information about a file based on its filename.
    Function Definition: int lstat(const char *path, struct stat *buf);
7. open : open a new file and obtain its file descriptor.
    Function Definition:
                        int open(const char *path, int oflags);
                        int open(const char *path, int oflags, mode_t mode);
8. read : read data into a buffer.
    Function Definition : size_t read(int fildes, void *buf, size_t nbytes);
9. stat :  used to determine information about a file based on its file path.
    Function Definition:  int stat(const char *path, struct stat *buf);
10. write : used to write data out of a buffer.
    Function Definition : size_t write(int fildes, const void *buf, size_t nbytes);


In contrast to these library function for system calls, there are other similar library function which are used for file I/O in C.  The operation takes place on pointers of type FILE(i.e. streams) and an integer is returned They are:

1. fopen: opens the filename pointed to, by filename using the given mode.
    Function Definition :  FILE *fopen(const char *filename, const char *mode);
2. fprintf: sends formatted output to a stream.
    Function Definition : int fprintf(FILE *stream, const char *format, ...)
3. fscanf:  reads formatted input from a stream.
    Function Definition: int fscanf(FILE *stream, const char *format, ...)
4. fputc: writes a character (an unsigned char) specified by the argument char to the specified stream     and advances the position indicator for the stream.
    Function Definition : int fputc(int char, FILE *stream)
5. fgetc: gets the next character (an unsigned char) from the specified stream and advances the               position indicator for the stream.
    Function Definition: int fgetc(FILE *stream)

Two other functions are used for I/O operations on binary files i.e. streams :

1. fread : reads data from the given stream into the array pointed to, by ptr.
    Function Definition : size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
2. fwrite :  writes data from the array pointed to, by ptr to the given stream.
    size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)

Binary Files and Text Files

http://fileinfo.com/help/binary_vs_text_files

Tuesday, August 25, 2015

Dynamic Memory Allocation in C

Many programmers think that dynamic memory allocation is difficult to learn. I was one of them. However, after going through some tutorials I found it to be quite easy.

Why dynamic memory allocation ?

Allocating large data objects are compile time is not always practical if data objects are used infrequently and for a short time. So, these data objects are allocated at run time.

What is dynamic in dynamic memory allocation ?

It is called dynamic because the memory is allocated at run-time as opposed to compile time. One more important thing to note about dynamic memory allocation is that the memory is allocated in heap as opposed to stack.

How to implement dynamic memory allocation ?

C provides four different functions for dynamic memory allocation. They are:

1. malloc : The malloc() function returns a void pointer to the allocated memory or NULL if the
memory could not be allocated. You should always check the returned pointer for NULL. Please note that there is a big difference between void pointer and NULL pointer. Void pointer does not have type but it does have a valid pointer to an address. However, NULL pointer does not have any address.

Syntax :  data_type *p = (data_type *) malloc(size_t);
(data_type *) is the cast. malloc returns a void pointer. So, it is important to type cast to correct pointer type.

Eg : int *data;
        *data = (int*) malloc(sizeof(int));

  •  The pointer returned by malloc() should be saved in a static variable, unless you are sure that the memory block will be freed before the pointer variable is discarded at the end of the block or the function.
  •  You should always free a block of memory that has been allocated by malloc() when you are finished with it. If you rely on the operating system to free the block when your program ends, there may be insufficient memory to satisfy additional requests for memory allocation during the rest of the program’s run.
  • Avoid allocating small blocks (that is, less than 25 or 50 bytes) of memory. There is always some overhead when malloc() allocates memory—16 or more bytes are allocated in addition to the requested memory.
  • Avoid allocating small blocks (that is, less than 25 or 50 bytes) of memory. There is always some overhead when malloc() allocates memory—16 or more bytes are allocated in addition to the requested memory.


2. calloc : The calloc library function assigns memory but with two major differences.
     a. Calloc takes two parameters, number of elements and size of element. The product of these                 elements determine the size of the memory block to allocate.
     b. It initializes the memory it allocates to zero.

      Syntax : data_type *p = (data_type *) calloc(n,size_t);
      Eg : int *data;
              *data = (int *) calloc(n, sizeof(int);

     There is a limit to the number of bytes that can be allocated by malloc or calloc function at one             time. That is 65,510 bytes in certain compiler.


3. free : This function returns allocated memory back to the operating system.The free() function is         almost foolproof. The pointer array is initialized to NULL which is a safe value because if someone tries to free the already freed pointer, there is no error. Errors could occur, however, when you try to free memory that

  • Was not allocated with one of the memory allocation functions,
  • Has been released through a prior call to free() or a call to realloc(),
  • Is currently in use by another thread in a multi-threaded operating system,
  • Is not yours to free.
4. realloc : When we are not sure as to how much of memory is required for certain operation we can first assign a small amount of memory using calloc() or malloc() and then call realloc() to make the block larger.

Syntax : void *realloc(void *ptr, size_t size) 

The pointer ptr points to memory block previously allocated with malloc, calloc or realloc. If is is NULL a new block of memory is allocated and the pointer to that block is returned.

size is the new size for the memory block, in bytes. If it is 0 and ptr points to an existing block of memory, the memory block pointed by ptr is deallocated and a NULL pointer is returned.

memset: This library function does not allocate or deallocate memory but initializes a block of memory to any value passed as it's parameter.

Syntax :  void *memset(void *str, int c, size_t n)


Parameters
  • str -- This is a pointer to the block of memory to fill.
  • c -- This is the value to be set. The value is passed as an int, but the function fills the block of memory using the unsigned char conversion of this value.
  • n -- This is the number of bytes to be set to the value.

Sunday, August 23, 2015

Array of Structure

We can use structure to store the value of one particular object but if we want to store the value of 100 such objects we need array of structure.

For eg: If we want to store the value of details of book like author, no of pages and price. We can define such structure as follows:

struct bookinfo{
    char[20] author;
    int pages;
    float price;
};

Now to define three similar structure we can define an array of the above defined structure as follows:

struct bookinfo record[3];

Lets's see this using a C program:

 #include
  struct bookinfo{
           char author[20];
           int pages;
           float price;
   };
 
   int main(){
       int i;
      struct bookinfo record[3];
      char suffix[3][3]={"st","nd","rd"};
      for(i=0;i<3 i="" p="">      {
             printf("Enter the author of first book: ");
             scanf("%s",record[i].author);
             printf("Enter the number of pages in the book: ");
             scanf("%d",&record[i].pages);
             printf("Enter the price of the book: ");
             scanf("%f",&record[i].price);
      }
 
      for(i=0;i<3 i="" p="">      {
 
         printf("\nThe author of %d%s book is: %s \n",i+1,suffix[i],record[i].author);
         printf("The number of pages in %d%s book is: %d \n",i+1,suffix[i],record[i].pages);
         printf("The price of %d%s book is: %f \n",i+1,suffix[i],record[i].price);
      }
      return 0;
  }


OUTPUT:

Enter the author of first book: fasdf
Enter the number of pages in the book: 32
Enter the price of the book: 34
Enter the author of first book: phy
Enter the number of pages in the book: 45
Enter the price of the book: 56.5
Enter the author of first book: math
Enter the number of pages in the book: 54
Enter the price of the book: 45.7

The author of 1st book is: fasdf
The number of pages in 1st book is: 32
The price of 1st book is: 34.000000

The author of 2nd book is: phy
The number of pages in 2nd book is: 45
The price of 2nd book is: 56.500000

The author of 3rd book is: math
The number of pages in 3rd book is: 54
The price of 3rd book is: 45.700001