Wednesday, 27 February 2013

Linux startup process


Linux start-up process



In Linux, the flow of control during a boot is from BIOS, to boot loader, to kernel. The kernel then starts the scheduler (to allow multi-tasking) and runs the first userland (i.e. outside kernel space) program Init (which is mostly responsible to run startup scripts for each runlevel), at which point the kernel goes idle unless called externally.
init (short for initialization) is a program for Unix-based computer operating systems that spawns all other processes. It runs as a daemon and typically has PID 1. The boot loader starts the kernel and the kernel starts init. If one were to delete init without a replacement, the system would encounter a kernel panic on the next reboot.
In detail:
  1. The BIOS performs hardware-platform specific startup tasks
  2. Once the hardware is recognized and started correctly, the BIOS loads and executes the partition boot code from the designated boot device, which contains phase 1 of a Linux boot loader. Phase 1 loads phase 2 (the bulk of the boot loader code). Some loaders may use an intermediate phase (known as phase 1.5) to achieve this since modern large disks may not be fully readable without further code.
  3. The boot loader often presents the user with a menu of possible boot options. It then loads the operating system, which decompresses into memory, and sets up system functions such as essential hardware and memory paging, before calling start_kernel().
  4. start_kernel() then performs the majority of system setup (interrupts, the rest of memory management, device initialization, drivers, etc.) before spawning separately, the idle process and scheduler, and the Init process(which is executed in user space).
  5. The Init process executes scripts as needed that set up all non-operating system services and structures in order to allow a user environment to be created, and then presents the user with a login screen. In Unix-based computer operating systemsinit (short for initialization) is a daemon process that is the direct or indirect ancestor of all other processes. It automatically adopts all orphaned processes. Init is the first process started during booting, and is typically assigned PID number 1. It is started by the kernel using a hard-coded filename, and if the kernel is unable to start it, a kernel panic will result. Init continues running until the system is shut down.
On shutdown, Init is called to close down all user space functionality in a controlled manner, again via scripted directions, following which Init terminates and the Kernel executes its own shutdown.

//copied from wikipedia..
For detaiiled description http://en.wikipedia.org/wiki/Linux_startup_process

BIOS
The name originated from the Basic Input Output System used in the CP/M operating system (released in 1976). The BIOS software is built into the PC, and is the first software run by a PC when powered on. The fundamental purposes of the BIOS are to initialize and test the system hardware components, and to load an operating system or other program from a mass memory device. The BIOS provides a consistent way for application programs and operating systems to interact with the keyboard, display, and other input/output devices. Variations in the system hardware are hidden by the BIOS from programs that use BIOS services instead of directly accessing the hardware.
http://en.wikipedia.org/wiki/BIOS



Tuesday, 26 February 2013

Difference between union and structures in C

union and structures in C


The difference between structure and union in c are: 1. union allocates the memory equal to the maximum memory required by the member of the union but structure allocates the memory equal to the total memory required by the members. 2. In union, one block is used by all the member of the union but in case of structure, each member have their own memory space  


Difference in their Usage:

While structure enables us treat a number of different variables stored at different in memory , a union enables us to treat the same space in memory as a number of different variables. That is a Union offers a way for a section of memory to be treated as a variable of one type on one occasion and as a different variable of a different type on another occasion.
There is frequent rwquirement while interacting with hardware to access access a byte or group of bytes simultaneously and sometimes each byte individually. Usually union is the answer.
=======Difference With example***** Lets say a structure containing an int,char and float is created and a union containing int char float are declared. struct TT{ int a; float b; char c; } Union UU{ int a; float b; char c; }
sizeof TT(struct) would be >9 bytes (compiler dependent-if int,float, char are taken as 4,4,1)
sizeof UU(Union) would be 4 bytes as supposed from above.If a variable in double exists in union then the size of union and struct would be 8 bytes and cumulative size of all variables in struct.  


Detailed Example:

struct foo 

char c; 
long l; 
char *p; 
}; 

union bar 

char c; 
long l; 
char *p; 
}; 

A struct foo contains all of the elements c, l, and p. Each element is 
separate and distinct. 

A union bar contains only one of the elements c, l, and p at any given 
time. Each element is stored in the same memory location (well, they all 
start at the same memory location), and you can only refer to the element 
which was last stored. (ie: after "barptr->c = 2;" you cannot reference 
any of the other elements, such as "barptr->p" without invoking undefined 
behavior.) 

Try the following program. (Yes, I know it invokes the above-mentioned
"undefined behavior", but most likely will give some sort of output on 
most computers.) 

==========
#include 

struct foo 

char c; 
long l; 
char *p; 
}; 

union bar 

char c; 
long l; 
char *p; 
}; 

int main(int argc,char *argv[])

struct foo myfoo;
union bar mybar;

myfoo.c = 1; 
myfoo.l = 2L; 
myfoo.p = "This is myfoo";

mybar.c = 1; 
mybar.l = 2L; 
mybar.p = "This is mybar";

printf("myfoo: %d %ld %s\n",myfoo.c,myfoo.l,myfoo.p);
printf("mybar: %d %ld %s\n",mybar.c,mybar.l,mybar.p);

return 0; 


==========

On my system, I get: 

myfoo: 1 2 This is myfoo
mybar: 100 4197476 This is mybar
==========
credit to original author. 

Structure: Structure is a combination elements, which can be predefined data types or other structure. The length/size of the structure is the sum of the length of its elements. 
In C, structures cannot containn functions. in C++ it can.

Union: Union is a combination elements, which can be predefined data types or other union . But, the size/length of union is the maximum of internal elements. 

the sizeof() operator returns the size slightly more than calculated size due to padding, which again depends on OS
== Answer == Union allocates the memory equal to the maximum memory required by the member of the union but structure allocates the memory equal to the total memory required by the members. In union,one block is used by all the member of the union but in case of structure, each member have their own memory space.
Union allocates the memory equal to the maximum memory requried by the member of the union but structure allocates the memory equal to sum of the memory allocated to its each individual members.
In Union, one block is used by all the member of union but in case of structure, each member have their own memory space.
Union allocates the memory equal to the maximum memory requried by the member of the union but structure allocates the memory equal to total memory requried by the members. In Union, one block is used by all the member of union but in case of structure, each member have their own memory space.

Monday, 25 February 2013

Memory allocation in C


Allocating Memory

So far you've learned how to declare and reserve a piece of memory space before it is used in your program. For instance, you have to specify the size of an array in your program (or the compiler has to figure out the size if you declare an unsized array) before you assign any data to it at runtime. In this lesson you'll learn to allocate memory space dynamically when your program is running. The four dynamic memory allocation functions covered in this lesson are

  • The malloc() function
  • The calloc() function
  • The realloc() function
  • The free() function

Allocating Memory at Runtime

There are many cases when you do not know the exact sizes of arrays used in your programs, until much later when your programs are actually being executed. You can specify the sizes of arrays in advance, but the arrays can be too small or too big if the numbers of data items you want to put into the arrays change dramatically at runtime.
Fortunately, C provides you with four dynamic memory allocation functions that you can employ to allocate or reallocate certain memory spaces while your program is running. Also, you can release allocated memory storage as soon as you don't need it. These four C functions, malloc(), calloc(), realloc(), and free(), are introduced in the following sections.

The malloc() Function

You can use the malloc() function to allocate a specified size of memory space.
The syntax for the malloc() function is
#include <stdlib.h>
void *malloc(size_t size);
Here size indicates the number of bytes of storage to allocate. The malloc() function returns a void pointer.
Note that the header file, stdlib.h, has to be included before the malloc() function can be called. Because the malloc() function returns a void pointer, its type is automatically converted to the type of the pointer on the left side of an assignment operator.
If the malloc() function fails to allocate a piece of memory space, it returns a null pointer. Normally, this happens when there is not enough memory. Therefore, you should always check the returned pointer from malloc() before you use it.
Listing 17.1 demonstrates the use of the malloc() function.

TYPE

Listing 17.1. Using the malloc() function.

1:  /* 17L01.c: Using the malloc function */
2:  #include <stdio.h>
3:  #include <stdlib.h>
4:  #include <string.h>
5:  /* function declaration */
6:  void StrCopy(char *str1, char *str2);
7:  /* main() function */
8:  main()
9:  {
10:    char str[] = "Use malloc() to allocate memory.";
11:    char *ptr_str;
12:    int result;
13:    /* call malloc() */
14:    ptr_str = malloc( strlen(str) + 1);
15:    if (ptr_str != NULL){
16:       StrCopy(str, ptr_str);
17:       printf("The string pointed to by ptr_str is:\n%s\n",
18:              ptr_str);
19:       result = 0;
20:    }
21:    else{
22:       printf("malloc() function failed.\n");
23:       result = 1;
24:    }
25:    return result;
26: }
27: /* function definition */
28: void StrCopy(char *str1, char *str2)
29: {
30:    int i;
31:
32:    for (i=0; str1[i]; i++)
33:       str2[i] = str1[i];
34:    str2[i] = `\0';
35: }
The following output is shown on the screen after the executable, 17L01.exe, of the program in Listing 17.1 is created and executed:
OUTPUT
C:\app>17L01
The string pointed to by ptr_str is:
Use malloc() to allocate memory.
C:\app>
ANALYSIS
The purpose of the program in Listing 17.1 is to use the malloc() function to allocate a piece of memory space that has the same size as a character string. Then, the content .of the string is copied to the allocated memory referenced by the pointer returned from the malloc() function. The content of the memory is displayed on the screen to prove that the memory space does contain the content of the string after the allocation and duplication.
Note that two more header files, stdlib.h and string.h, are included in lines 3 and 4, respectively, for the functions malloc() and strlen(), which are called in line 14.
Line 10 declares a char array, str, that is initialized with a character string of "Use malloc() to allocate memory.". A char pointer variable, ptr_str, is declared in line 11.
The statement in line 14 allocates a memory space of strlen(str)+1 bytes by calling the malloc() function. Because the strlen() function does not count the null character at the end of a string, adding 1 to the value returned by strlen(str) gives the total number of bytes that need to be allocated. The value of the returned pointer is assigned to the char pointer variable ptr_str after the malloc() function is called in line 14.
The if-else statement in lines 15_24 checks the returned pointer from the malloc() function. If it's a null pointer, an error message is printed out, and the return value of the main() function is set to 1 in lines 22 and 23. (Remember that a nonzero value returned by the return statement indicates an abnormal termination.)
But if the returned pointer is not a null pointer, the start address of the str array and the pointer ptr_str are passed to a subfunction called StrCopy() in line 16. The StrCopy() function, whose definition is given in lines 28_35, copies the content of the str array to the allocated memory pointed to by ptr_str. Then, the printf() function in lines 17 and 18 prints out the copied content in the allocated memory. Line 19 sets the return value to 0 after the success of the memory allocation and string duplication.
The output on my screen shows that a piece of memory has been allocated and that the string has been copied to the memory.
There is a potential problem if you keep allocating memory, because there is always a limit. You can easily run out of memory when you just allocate memory without releasing it. In the next section, you'll learn how to use the free() function to free up memory spaces allocated for you when you don't need them.

Releasing Allocated Memory with free()

Because memory is a limited resource, you should allocate an exactly sized piece of memory right before you need it, and release it as soon as you don't need it.
The program in Listing 17.2 demonstrates how to release allocated memory by calling the free() function.

TYPE

Listing 17.2. Using the free() and malloc() functions together.

1:  /* 17L02.c: Using the free() function */
2:  #include <stdio.h>
3:  #include <stdlib.h>
4:  /* function declarations */
5:  void DataMultiply(int max, int *ptr);
6:  void TablePrint(int max, int *ptr);
7:  /* main() function */
8:  main()
9:  {
10:    int *ptr_int, max;
11:    int termination;
12:    char key = `c';
13:
14:    max = 0;
15:    termination = 0;
16:    while (key != `x'){
17:       printf("Enter a single digit number:\n");
18:       scanf("%d", &max);
19:
20:       ptr_int = malloc(max * max * sizeof(int));  /* call malloc() */
21:       if (ptr_int != NULL){
22:          DataMultiply(max, ptr_int);
23:          TablePrint(max, ptr_int);
24:          free(ptr_int);
25:       }
26:       else{
27:          printf("malloc() function failed.\n");
28:          termination = 1;
29:          key = `x';  /* stop while loop */
30:       }
31:       printf("\n\nPress x key to quit; other key to continue.\n");
32:       scanf("%s", &key);
33:    }
34:    printf("\nBye!\n");
35:    return termination;
36: }
37: /* function definition */
38: void DataMultiply(int max, int *ptr)
39: {
40:    int i, j;
41:
42:    for (i=0; i<max; i++)
43:       for (j=0; j<max; j++)
44:          *(ptr + i * max + j) = (i+1) * (j+1);
45: }
46: /* function definition */
47: void TablePrint(int max, int *ptr)
48: {
49:    int i, j;
50:
51:    printf("The multiplication table of %d is:\n",
52:            max);
53:    printf(" ");
54:    for (i=0; i<max; i++)
55:       printf("%4d", i+1);
56:    printf("\n ");
57:    for (i=0; i<max; i++)
58:       printf("----", i+1);
59:    for (i=0; i<max; i++){
60:       printf("\n%d|", i+1);
61:       for (j=0; j<max; j++)
62:         printf("%3d ", *(ptr + i * max + j));
63:    }
64: }
While the executable 17L02.exe is being run, I enter two integers, 4 and 2 (highlighted in the following output), to obtain a multiplication table for each; then I quit running the program by pressing the x key:
OUPUT
C:\app>17L02
Enter a single digit number:
4
The multiplication table of 4 is:
   1   2   3   4
 --------------
1| 1   2   3   4
2| 2   4   6   8
3| 3   6   9  12
4| 4   8  12  16
Press x-key to quit; other key to continue.
C
Enter a single digit number:
2
The multiplication table of 2 is:
   1   2
 ------
1| 1   2
2| 2   4
Press x-key to quit; other key to continue.
x
Bye!
C:\app>
ANALYSIS
The purpose of the program in Listing 17.2 is to build a multiplication table based on the integer given by the user. The program can continue building multiplication tables until the user presses the x key to quit. The program also stops execution if the malloc() function fails.
To show you how to use the free() function, the program allocates a temporary memory storage to hold the items of a multiplication table. As soon as the content of a multiplication table is printed out, the allocated memory is released by calling the free() function.
Lines 5 and 6 declare two functions, DataMultiply() and TablePrint(), respectively. The former is for performing multiplication and building a table, whereas the latter prints out the table on the screen. The definitions of the two functions are given in lines 38_45 and lines 47_64, respectively.
Inside the main() function, there is a while loop in lines 16_33 that keeps asking the user to enter an integer number (see lines 17 and 18) and then building a multiplication table based on the integer.
To hold the result of the multiplication, the statement in line 20 allocates a memory storage that has the size of max*max*sizeof(int), where the int variable max contains the integer value entered by the user. Note that the sizeof(int) expression gives the byte number of the int data type of the computer on which the program is being run.
If the malloc() function returns a null pointer, the return value of the main() function is set to 1 to indicate an abnormal termination (see line 28), and the while loop is stopped by assigning the key variable with `x' in line 29.
Otherwise, if the malloc() function allocates a memory storage successfully, the DataMultiply() function is called in line 22 to calculate each multiplication. The results are saved into the memory storage pointed to by the ptr_int pointer. Then the multiplication table is printed out by calling the TablePrint() function in line 23.
As soon as I no longer need to keep the multiplication table, I call the free() function in line 24 to release the allocated memory storage pointed to by the ptr_int pointer.
If I did not release the memory, the program would take more and more memory as the user keeps entering integer numbers to build more multiplication tables. Eventually, the program would either crash the operating system or be forced to quit. By using the free() and malloc() functions, I am able to keep running the program by taking the exact amount of memory storage I need, no more and no less.

The calloc() Function

Besides the malloc() function, you can also use the calloc() function to allocate a memory storage dynamically. The differences between the two functions are that the latter takes two arguments and that the memory space allocated by calloc() is always initialized to 0. There is no such guarantee that the memory space allocated by malloc() is initialized to 0.
The syntax for the calloc() function is
#include <stdlib.h>
void *calloc(size_t nitem, size_t size);
Here nitem is the number of items you want to save in the allocated memory space. size gives the number of bytes that each item takes. The calloc() function returns a void pointer too.
If the calloc() function fails to allocate a piece of memory space, it returns a null pointer.
Listing 17.3 contains an example of using the calloc() function. The initial value of the memory space allocated by calloc() is printed out.

TYPE

Listing 17.3. Using the calloc() function.

1:  /* 17L03.c: Using the calloc() function */
2:  #include <stdio.h>
3:  #include <stdlib.h>
4:  /* main() function */
5:  main()
6:  {
7:     float *ptr1, *ptr2;
8:     int i, n;
9:     int termination = 1;
10:
11:    n = 5;
12:    ptr1 = calloc(n, sizeof(float));
13:    ptr2 = malloc(n * sizeof(float));
14:    if (ptr1 == NULL)
15:       printf("malloc() failed.\n");
16:    else if (ptr2 == NULL)
17:       printf("calloc() failed.\n");
18:    else {
19:       for (i=0; i<n; i++)
20:          printf("ptr1[%d]=%5.2f,  ptr2[%d]=%5.2f\n",
21:           i, *(ptr1 + i), i, *(ptr2 + i));
22:       free(ptr1);
23:       free(ptr2);
24:       termination = 0;
25:    }
26:    return termination;
27: }
The following output appears on the screen after running the executable 17L03.exe:
OUTPUT
C:\app>17L03
ptr1[0] = 0.00,  ptr2[0] = 7042.23
ptr1[1] = 0.00,  ptr2[1] = 1427.00
ptr1[2] = 0.00,  ptr2[2] = 2787.14
ptr1[3] = 0.00,  ptr2[3] =    0.00
ptr1[4] = 0.00,  ptr2[4] = 5834.73
C:\app>
ANALYSIS
The purpose of the program in Listing 17.3 is to use the calloc() function to allocate a piece of memory space. To prove that the calloc() function initializes the allocated memory space to 0, the initial values of the memory are printed out. Also, an-
other piece of memory space is allocated by using the malloc() function, and the initial values of the second memory space is printed out too.
As you see in line 12, the calloc() function is called with two arguments passed to it: the int variable n and the sizeof(float) expression. The float pointer variable ptr1 is assigned the value returned by the calloc() function.
Likewise, the malloc() function is called in line 13. This function only takes one argument that specifies the total number of bytes that the allocated memory should have. The value returned by the malloc() function is then assigned to another float pointer variable, ptr2.
From lines 12 and 13, you can tell that the calloc() and malloc() functions actually plan to allocate two pieces of memory space with the same size.
The if-else-if-else statement in lines 14_25 checks the two values returned from the calloc() and malloc() functions and then prints out the initial values from the two allocated memory spaces if the two return values are not null.
I ran the executable program in Listing 17.3 several times. Each time, the initial value from the memory space allocated by the calloc() function was always 0. But there is no guarantee for the memory space allocated by the malloc() function. The output shown here is one of the results from running the executable program on my machine. You can see that there is some "garbage" in the memory space allocated by the malloc() function. That is, the initial value in the memory is unpredictable. (Sometimes, the initial value in a memory block allocated by the malloc() function is 0. But it is not guaranteed that the initial value is always 0 each time when the malloc() function is called.)

The realloc() Function


The realloc() function changes the size of a block of memory that was previously allocated with malloc() or calloc(). The function prototype is
void *realloc(void *ptr, size_t size);
The ptr argument is a pointer to the original block of memory. The new size, in bytes, is specified bysize. There are several possible outcomes with realloc():
  • If sufficient space exists to expand the memory block pointed to by ptr, the additional memory is allocated and the function returns ptr.
  • If sufficient space does not exist to expand the current block in its current location, a new block of the size for size is allocated, and existing data is copied from the old block to the beginning of the new block. The old block is freed, and the function returns a pointer to the new block.
  • If the ptr argument is NULL, the function acts like malloc(), allocating a block of size bytes and returning a pointer to it.
  • If the argument size is 0, the memory that ptr points to is freed, and the function returns NULL.
  • If memory is insufficient for the reallocation (either expanding the old block or allocating a new one), the function returns NULL, and the original block is unchanged.

The realloc() function gives you a means to change the size of a piece of memory space allocated by the malloc() function, the calloc() function, or even itself.
The syntax for the realloc() function is
#include <stdlib.h>
void *realloc(void *block, size_t size);
Here block is the pointer to the start of a piece of memory space previously allocated. size specifies the total byte number you want to change to. The realloc() function returns a void pointer.
The realloc() function returns a null pointer if it fails to reallocate a piece of memory space.
The realloc() function is equivalent to the malloc() function if the first argument passed to realloc() is NULL. In other words, the following two statements are equivalent:
ptr_flt = realloc(NULL, 10 * sizeof(float));
ptr_flt = malloc(10 * sizeof(float));
Also, you can use the realloc() function as the free() function. You do this by passing 0 to realloc() as its second argument. For instance, to release a block of memory pointed to by a pointer ptr, you can either call the free() function like this:
free(ptr);
or use the realloc() function in the following way:
realloc(ptr, 0);
The program in Listing 17.4 demonstrates the use of the realloc() function in memory reallocation.

TYPE

Listing 17.4. Using the realloc() function.

1:  /* 17L04.c: Using the realloc() function */
2:  #include <stdio.h>
3:  #include <stdlib.h>
4:  #include <string.h>
5:  /* function declaration */
6:  void StrCopy(char *str1, char *str2);
7:  /* main() function */
8:  main()
9:  {
10:    char *str[4] = {"There's music in the sighing of a reed;",
11:                    "There's music in the gushing of a rill;",
12:                    "There's music in all things if men had ears;",
13:                    "There earth is but an echo of the spheres.\n"
14:                   };
15:    char *ptr;
16:    int i;
17:
18:    int termination = 0;
19:
20:    ptr = malloc((strlen(str[0]) + 1) * sizeof(char));
21:    if (ptr == NULL){
22:      printf("malloc() failed.\n");
23:      termination = 1;
24:    }
25:    else{
26:      StrCopy(str[0], ptr);
27:      printf("%s\n", ptr);
28:      for (i=1; i<4; i++){
29:        ptr = realloc(ptr, (strlen(str[i]) + 1) * sizeof(char));
30:        if (ptr == NULL){
31:          printf("realloc() failed.\n");
32:          termination = 1;
33:          i = 4;    /* break the fro loop */
34:        }
35:        else{
36:          StrCopy(str[i], ptr);
37:          printf("%s\n", ptr);
38:        }
39:      }
40:    }
41:    free(ptr);
42:    return termination;
43: }
44: /* function definition */
45: void StrCopy(char *str1, char *str2)
46: {
47:    int i;
48:
49:    for (i=0; str1[i]; i++)
50:       str2[i] = str1[i];
51:    str2[i] = `\0';
52: }
The following output is obtained by running the executable 17L04.exe:
OUTPUT
C:\app>17L04
There's music in the sighing of a reed;
There's music in the gushing of a rill;
There's music in all things if men had ears;
There earth is but an echo of the spheres.
C:\app>
ANALYSIS
The purpose of the program in Listing 17.4 is to allocate a block of memory space to hold a character string. There are four strings in this example, and the length of each string may vary. I use the realloc() function to adjust the size of the previously allocated memory so it can hold a new string.

As you can see in lines 10_13, there are four character strings containing a lovely poem written by Lord Byron. (You can tell that I love Byron's poems.) Here I use an array of pointers, str, to refer to the strings.
A piece of memory space is first allocated by calling the malloc() function in line 20. The size of the memory space is determined by the (strlen(str[0])+1)*sizeof(char) expression. As mentioned earlier, because the C function strlen() does not count the null character at the end of a string, you have to remember to allocate one more piece of memory to hold the full size of a string. The sizeof(char) expression is used here for portability, although the char data type is 1 byte long on most computers.
Exercise 4 at the end of this lesson asks you to rewrite the program in Listing 17.4 and replace the malloc() and free() functions with their equivalent formats of the realloc() functions.
If the malloc() function doesn't fail, the content of the first string pointed to by the str[0] pointer is copied to the block memory allocated by malloc(). To do this, a function called StrCopy() is called in line 26. Lines 45_52 give the definition of StrCopy().
The for loop, in lines 28_39, copies the remaining three strings, one at a time, to the block of memory pointed to by ptr. Each time, the realloc() function is called in line 29 to reallocate and adjust the previously allocated memory space based on the length of the next string whose content is about to be copied to the memory block.
After the content of a string is copied to the memory block, the content is also printed out (see lines 27 and 37).
In this example, a block of memory space is allocated and adjusted based on the length of each of the four strings. The realloc() function, as well as the malloc() function, does the memory allocation and adjustment dynamically.

Summary

In this lesson you've learned the following:
  • In C, there are four functions that can be used to allocate, reallocate, or release a block of memory space dynamically at runtime.
  • The malloc() function allocates a block of memory whose size is specified by the argument passed to the function.
  • The free() function is used to free up a block of memory space previously allocated by the malloc(), calloc(), or realloc() function
  • The calloc() function can do the same job as the malloc() function. In addition, the calloc() function can initialize the allocated memory space to 0.
  • The realloc() function is used to reallocate a block of memory that has been allocated by the malloc() or calloc() function.
  • If a null pointer is passed to the realloc() function as its first argument, the function acts like the malloc() function.
  • If the second argument of the realloc() function is set to 0, the realloc() function is equivalent to the free() function that releases a block of allocated memory.
  • You have to include the header file stdlib.h before you can call the malloc(), calloc(), realloc(), or free() function.
  • You should always check the values returned from the malloc(), calloc(), or realloc() function, before you use the allocated memory made by these functions.
In the next lesson you'll learn more about data types in C.

Q&A

Q Why do you need to allocate memory at runtime?
A Very often, you don't know the exact sizes of arrays until your program is being run. You might be able to estimate the sizes for those arrays, but if you make those arrays too big, you waste the memory. On the other hand, if you make those arrays too small, you're going to lose data. The best way is to allocate blocks of memory dynamically and precisely for those arrays when their sizes are determined at runtime. There are four C library functions, malloc(), calloc(), realloc(), and free(), which you can use in memory allocation at runtime.
Q What does it mean if the malloc() function returns a null pointer?
A If the malloc() function returns a null pointer, it means the function fails to allocate a block of memory whose size is specified by the argument passed to the function. Normally, the failure of the malloc() function is caused by the fact that there is not enough memory to allocate. You should always check the value returned by the malloc() function to make sure that the function has been successful before you use the block of memory allocated by the function.
Q What are the differences between the calloc() and malloc() functions?
A Basically, there are two differences between the calloc() and malloc() functions, although both of them can do the same job. The first difference is that the calloc() function takes two arguments, while the malloc() function takes only one. The second one is that the calloc() function initializes the allocated memory space to 0, whereas there is no such guarantee made by the malloc() function.
Q Is the free() function necessary?
A Yes. The free() function is very necessary, and you should use it to free up allocated memory blocks as soon as you don't need them. As you know, memory is a limited resource in a computer. Your program shouldn't take too much memory space when it allocates blocks of memory. One way to reduce the size of memory taken by your program is to use the free() function to release the unused allocated memory in time.

Storage Classes


Storage Classes


static

static is sometimes a useful keyword. It is a common misbelief that the only purpose is to make a variable stay in memory.
When you declare a function or global variable as static it will become internal. You cannot access the function or variable through the extern (see below) keyword from other files in your project.
When you declare a local variable as static, it is created just like any other variable. However, when the variable goes out of scope (i.e. the block it was local to is finished) the variable stays in memory, retaining its value. The variable stays in memory until the program ends. While this behaviour resembles that of global variables, static variables still obey scope rules and therefore cannot be accessed outside of their scope.
Variables declared static are initialized to zero (or for pointers, NULL) by default.
You can use static in (at least) two different ways. Consider this code, and imagine it is in a file called jfile.c:

#include <stdio.h>
 
static int j = 0;
 
void up(void)
{
   /* k is set to 0 when the program starts. The line is then "ignored"
    * for the rest of the program (i.e. k is not set to 0 every time up()
    * is called)
    */
   static int k = 0;
   j++;
   k++;
   printf("up() called.   k= %2d, j= %2d\n", k , j);
}
 
void down(void)
{
   static int k = 0;
   j--;
   k--;
   printf("down() called. k= %2d, j= %2d\n", k , j);
}
 
int main(void)
{
   int i;
 
   /* call the up function 3 times, then the down function 2 times */
   for (i= 0; i < 3; i++)
      up();
   for (i= 0; i < 2; i++)
      down();
 
   return 0;
}
The j var is accessible by both up and down and retains its value. The k vars also retain their value, but they are two different variables, one in each of their scopes. Static vars are a good way to implement encapsulation, a term from the object-oriented way of thinking that effectively means not allowing changes to be made to a variable except through function calls.
Running the program above will produce the following output:
up() called.   k=  1, j=  1
up() called.   k=  2, j=  2
up() called.   k=  3, j=  3
down() called. k= -1, j=  2
down() called. k= -2, j=  1
Features of static variables :
    1. Keyword used        - static
    2. Storage             - Memory
    3. Default value       - Zero
    4. Scope               - Local to the block in which it is declared
    5. Lifetime            - Value persists between different function calls
    6. Keyword optionality - Mandatory to use the keyword

extern

extern is used when a file needs to access a variable in another file that it may not have #included directly. Therefore, extern does not actually carve out space for a new variable, it just provides the compiler with sufficient information to access the remote variable.
Features of external variable :
    1. Keyword used        - extern
    2. Storage             - Memory
    3. Default value       - Zero
    4. Scope               - Global (all over the program)
    5. Lifetime            - Value persists till the program's execution comes to an end
    6. Keyword optionality - Optional if declared outside all the functions

volatile

volatile is a special type modifier which informs the compiler that the value of the variable may be changed by external entities other than the program itself. This is necessary for certain programs compiled with optimizations – if a variable were not defined volatile then the compiler may assume that certain operations involving the variable are safe to optimize away when in fact they aren't. volatile is particularly relevant when working with embedded systems (where a program may not have complete control of a variable) and multi-threaded applications.

auto

auto is a modifier which specifies an "automatic" variable that is automatically created when in scope and destroyed when out of scope. If you think this sounds like pretty much what you've been doing all along when you declare a variable, you're right: all declared items within a block are implicitly "automatic". For this reason, the auto keyword is more like the answer to a trivia question than a useful modifier, and there are lots of very competent programmers that are unaware of its existence.
Features of automatic variables :
    1. Keyword used        - auto
    2. Storage             - Memory
    3. Default value       - Garbage value (random value)
    4. Scope               - Local to the block in which it is defined
    5. Lifetime            - Value persists till the control remains within the block
    6. Keyword optionality - Optional

register

register is a hint to the compiler to attempt to optimize the storage of the given variable by storing it in a register of the computer's CPU when the program is run. Most optimizing compilers do this anyway, so use of this keyword is often unnecessary. In fact, ANSI C states that a compiler can ignore this keyword if it so desires – and many do. Microsoft Visual C++ is an example of an implementation that completely ignores the register keyword.
Features of register variables :
    1. Keyword used        - register
    2. Storage             - CPU registers (values can be retrieved faster than from memory)
    3. Default value       - Garbage value
    4. Scope               - Local to the block in which it is defined
    5. Lifetime            - Value persists till the control remains within the block
    6. Keyword optionality - Mandatory to use the keyword

  • A variable declared within a block has block scope. Such a variable is also called a local variable and is only visible within the block
  • The goto label has function scope, which means that it is visible through the whole block of the function within which the label is placed. No two goto labels share the same name within a function block.
  • A variable declared with the static specifier outside a function has file scope, which means that it is visible throughout the entire source file in which the variable is declared.
  • A variable declared outside a function is said to have program scope. Such a variable is also called a global variable. A global variable is visible in all source files that make up an executable program.
  • A variable with block scope has the most limited visibility. On the other hand, a variable with program block is the most visible through all files, functions, and other blocks that make up the program.
  • The storage class of a variable refers to the combination of its spatial and temporal regions (that is, its scope and duration.)
  • By default, a variable with block scope has an auto duration, and its memory storage is temporary.
  • A variable declared with the static specifier has permanent memory storage, even though the function in which the variable is declared has been called and the function scope has exited.
  • A variable declared with the register specifier may be stored in a register to speed up the performance of a program; however, the compiler can ignore the specifier if there is no register available or if some other restrictions have to apply.
  • You can also allude to a global variable defined elsewhere by using the extern specifier from the current source file.
  • To make sure the value saved by a variable cannot be changed, you can declare the variable with the const modifier.
  • If you want to let the compiler know that the value of a variable can be changed without an explicit assignment statement, declare the variable with the volatile modifier so that the compiler will turn off optimizations on expressions involving the variable.
In the next lesson you'll learn about function declarations and prototypes in C.

Q&A

Q Can a global variable be hidden by a local variable with block scope?
A Yes. If a local variable shares the same name with a global variable, the global
variable can be hidden by the local variable for the scope of the block within which the local variable is defined with block scope. However, outside the block, the local variable cannot be seen, but the global variable becomes visible again.
Q Why do you need the static specifier?
A In many cases, the value of a variable is needed, even if the scope of the block, in which the variable is declared, has exited. By default, a variable with block scope has a temporary memory storage—that is, the lifetime of the variable starts when the block is executed and the variable is declared, and ends when the execution is finished. Therefore, to declare a variable with permanent duration, you have to use the static specifier to indicate to the compiler that the memory location of the variable and the value stored in the memory location should be retained after the execution of the block.
Q Does using the register specifier guarantee to improve the performance of a program?
A Not really. Declaring a variable with the register specifier only suggests to the compiler that the variable be stored in a register. But there is no guarantee that the variable will be stored in a register. The compiler can ignore the request based on the availability of registers or other restrictions.
Q When you declare a variable with the extern specifier, do you define the variable or allude to a global variable elsewhere?
A When a variable is declared with the extern specifier, the compiler considers the declaration of the variable as an allusion rather than a definition. The compiler will therefore look somewhere else to find a global variable to which the variable with extern alludes.

Tuesday, 5 February 2013

volatile keyword

volatile keyword

Use of volatile

The compilation system tries to reduce code size and execution time on all machines, by optimizing code. It is programmer responsibility to inform compilation system that certain code (or variable) should not be optimized. Many programmers do not understand when to use volatile to inform compilation system that certain code should not be optimized or what it does. Although (no doubt) their program work, they do not exploit the full power of the language.

A variable should be declared volatile whenever its value can be changed by something beyond the control of the program in which it appears, such as a concurrently executing thread. Volatile, can appear only once in a declaration with any type specifier; however, they cannot appear after the first comma in a multiple item declaration. For example, the following declarations are legal


/* Let T denotes some data type */
typedef volatile T i; 
volatile T i;
T volatile   i ; 
And the following declaration is illegal
T i, volatile vi ;
Volatile qualifiers can be used to change the behavior of a type. For example,
volatile int p = 3;
declares and initializes an object with type volatile int whose value will be always read from memory.

Syntax

Keyword volatile can be placed before or after the data type in the variable definition. For example following declaration are identical:
Volatile T a =3;
T volatile a=3; 
The declaration declares and initializes an objet with type volatile T whose value will be always read from memory

Pointer declaration

Volatile T * ptr; 
T volatile * ptr; 
Ptr is a a pointer to a volatile T:
volatile pointer to a volatile variable  
int volatile * volatile ptr; 
volatile can be applied to derived types such as an array type ,in that case, the element is qualified, not the array type. When applied to struct types entire contents of the struct become volatile. You can apply the volatile qualifier to the individual members of the struct. Type qualifiers are relevant only when accessing identifiers as l-values in expressions. volatile does not affects the range of values or arithmetic properties of the object.. To declare the item pointed to by the pointer as volatile, use a declaration of the form:
volatile T *vptr;


To declare the value of the pointer - that is, the actual address stored in the pointer - as volatile, use a declaration of the form:
T* volatile ptrv;

Use of volatile

- An object that is a memory-mapped I/O port
- An object variable that is shared between multiple concurrent processes
- An object that is modified by an interrupt service routine
- An automatic object declared in a function that calls setjmp and whose value is-changed between the call to setjmp and a corresponding call to longjmp

# An object that is a memory-mapped I/O port

an 8 bit , memory -mapped I/O port at physical address 0X15 can be declared as
char const ptr=(char*)0X15 ;
*ptr access the port consider following code fragment to set the third bit of the output port at periodic intervals
*ptr = 0;
while(*ptr){
     *ptr = 4 ;
     *ptr = 0 ;
}
the above code may be optimize as
*ptr = 0
while(0) {
}
*ptr is assigned 0 before value 4 is used ( and value of *ptr never changes ( same constant is always assigned to it)
volatile keyword is used to suppress these optimization the compiler assumes that the value can change any time , even if no explicit code modify it to suppress all optimization declare ptr as
 volatile char * const ptr = (volatile char*)0x16
this declaration say the object at which ptr points can change without notice , but that ptr itself is a constant whose value never change

# An object that is shared between multiple concurrent processes

if two threads/tasks concurrently assign distinct values to the same shared non-volatile variable, a subsequent use of that variable may obtain a value that is not equal to either of the assigned values, but some implementation-dependent mixture of the two values. so a global variable references by multiple thread programmers must declare shared variable as volatile.
#include
#include
volatile int num ;
void* foo()
{
while(1) {
      ++num ;
      sleep(1000);
      }
}

main()
{
 int p ;
 void *targ =NULL ;
 thread_t id ;
 num = 0;
 p = thr_create((void*)NULL , 0,foo,targ,0,&id);
 if(!p)  printf(" can not create thread ");

 while(1) 
 {
   printf("%d" , num ) ;
 }
}
the compiler may use a register to store the num variable in the main thread , so the change to the value by the second thread are ignored . The volatile modifier is a away of telling the compiler that no optimization applied to the variable its value be not placed in register and value may change outside influence during evaluation

# An automatic object declared in a function that calls setjmp and whose value is-changed between the call to setjmp and a corresponding call to longjmp

Variables local to functions that call setjmp is most often used. When an automatic object is declared in a function that calls setjmp, the compilation system knows that it has to produce code that exactly matches what the programmer wrote. Therefore, the most recent value for such an automatic object will always be in memory (not just in a register) and as such will be guaranteed to be up-to-date when longjmp is called. Without volatile variable is undefined by the standard whether the result one see differs with or without optimization simply reflects that fact Consider following code
#include
static jmp_buf  buf ;
main( )
{
        volatile  int b;
        b =3 ;
        if(setjmp(buf)!=0)  {
        printf("%d ", b) ;  
        exit(0);
        }
        b=5;
       longjmp(buf , 1) ;
 }
volatile variable isn't affected by the optimization. So value of b is after the longjump is the last value variable assigned. Without volatile b may or may not be restored to its last value when the longjmp occurs. For clear understanding assembly listing of above program by cc compiler has been given below.
/*Listing1: Assembly code fragment of above program
   Produced by cc compiler  when volatile is used*/



.file "vol.c"
main:
 pushl %ebp
 movl %esp, %ebp
 subl $20, %esp
 movl $3, -4(%ebp)
 pushl $buf
 call _setjmp
 addl $16, %esp
 testl %eax, %eax
 je .L18
 subl $8, %esp
 movl -4(%ebp), %eax
 pushl %eax
 pushl $.LC0
 call printf
 movl $0, (%esp)
 call exit
 .p2align 2
.L18:
 movl $5, -4(%ebp)
 subl $8, %esp
 pushl $1
 pushl $buf
 call longjmp

 /*Listing 2:Assemply code fragment of  above program
   produced by cc compile witout volatile keword */

.file "wvol.c"
main:
 pushl %ebp
 movl %esp, %ebp
 subl $20, %esp
 pushl $buf
 call _setjmp
 addl $16, %esp
 testl %eax, %eax
 je .L18
 subl $8, %esp
 pushl $3
 pushl $.LC0
 call printf
 movl $0, (%esp)
 call exit
 .p2align 2
.L18:
 subl $8, %esp
 pushl $1
 pushl $buf
 call longjmp

/listing 3: difference between listing 1 and listing 3 ***/

< .file "vol.c"
---
> .file "wvol.c"
<  movl $3, -4(%ebp) 
<  movl -4(%ebp), %eax
<  pushl %eax
>  pushl $3
<  movl $5, -4(%ebp) / * store in stack */

From above listing 3 it is clear that when you use setjmp and longjmp, the only automatic variables guaranteed to remain valid are those declared volatile.

# An object modified by an interrupt service routine

Interrupt service routines often set variables that are tested in main line code. One problem that arises as soon as you use interrupt is that interrupt routines need to communicate with rest of the code .A interrupt may update a variable num that is used in main line of code .An incorrect implementation of this might be:
static lon int  num ;
void interrupt update(void)
{
++num ;
}
main()
{
long  val ;
val  = num ;
while(val !=num)
val = num ;
rturn val ;
}
When compilation system execute while statement, the optimizer in compiler may notice that it read the value num once already and that value is still in the register. Instead of re reading the value from memory, compiler may produce code to use the (possibly messed up) value in the register defeating purpose of original C program. Some compiler may optimize entire while loop assuming that since the value of num was just assigned to val , the two must be equal and condition in while statement will therefore always be false .To avoid this ,you have to declare num to be volatile that warns compilers that certain variables may change because of interrupt routines.
static volatile  long int num ;
With volatile keyword in the declaration the compiler knows that the value of num must b read from memory every time it is referenced.

Conclusion

When using exact semantics is necessary, volatile should be used. If you are given a piece of touchy code given as above. It is a good idea in any case to look the compiler outputting listing at the assembly language to be sure that compiler produce code that makes sense.

Kernel space and User space


kernel space and user space

A conventional computer operating system usually segregates virtual memory into kernel space and user space. Kernel space is strictly reserved for running the kernel, kernel extensions, and most device drivers. In contrast, user space is the memory area where all user mode applications work and this memory can be swapped out when necessary.

The really simplified answer is that the kernel runs in kernel space, and normal programs run in user space. User space is basically a form of sand-boxing -- it restricts user programs so they can't mess with memory (and other resources) owned by other programs or by the OS kernel. This limits (but usually doesn't entirely eliminate) their ability to do bad things like crashing the machine.
The kernel is the core of the operating system. It normally has full access to all memory and machine hardware (and everything else on the machine. To keep the machine as stable as possible, you normally want only the most trusted, well-tested code to run in kernel mode/kernel space.
The stack is just another part of memory, so naturally it's segregated right along with the rest of memory.
The random access memory (RAM) can be divided into two distinct regions namely - the kernel space and the user space.
The kernel runs in the part of memory entitled to it. This part of memory cannot be accessed directly by the processes of the normal users, while as the kernel can access all parts of the memory. To access some part of the kernel, the user processes have to use the predefined system calls i.e. openread,write etc. Also, the C library functions like printf call the system call write in turn.
The system calls act as an interface between the user processes and the kernel processes. The access rights are placed on the kernel space in order to stop the users from messing up with the kernel, unknowingly.
So, when a system call occurs, a software interrupt is sent to the kernel. The CPU may hand over the control temporarily to the associated interrupt handler routine. The kernel process which was halted by the interrupt resumes after the interrupt handler routine finishes its job.