Wednesday, 2 October 2013

[Operating System #1] Handling Child Process

We know that a new process can be created using fork() system call. This new process we call it as a Child Process.

fork():
---------
fork() prototype declaration:
            #include<unistd.h>
            pid_t fork(void);
Return: It returns two results. One result is Process ID (PID) of new process (child process), which is returned to parent process.  Second result is 0 (if child process is created successfully.), which is returned to child process.

We will identify child and parent process using this return value only.

Sample code:
----------------
                pid_t child_pid;
                child_pid = fork();
                if (child_pid == 0)
                {  /* child process */
                } else {
                    /* parent process */
                }

The child will have its own PCB (Process Control Block), so this process is assigned with a PID. We use getpid() call to get the PID of the process. Similarly, we use getppid() call to get the PID of its parent process.
getpid() & getppid():
--------------------------
These calls returns PID of the process of integer datatype.
This child process will share same address space with its parent i.e. it shares stack segment, data segment and code segment and it has its own PCB.

------------------------------------------------------------------------------
Example-1
========

  1. #include<unistd.h>
  2. #include<stdio.h>

  3. #define CHILD 0

  4. int main()
  5. {
  6. pid_t child_pid;

  7. printf("Before fork: pid: %d\n", getpid());
  8. child_pid = fork();
  9. printf("Hello Fork: pid: %d, parent_pid: %d, childpid: %d\n", getpid(), getppid(), child_pid);
  10. return 0;
  11. }

output:
======
Before fork: pid: 2164
Hello Fork: pid: 2164, parent_pid: 1924 (bash), childpid: 2165
Hello Fork: pid: 2165, parent_pid: 1, childpid: 0

Observation:
==========
The code after fork() function will be executed twice. One time for parent process and 2nd time for child process. Since, child process shares same address space it includes code segment also.

Parent process (2164) is executed before child and got terminated, its parent process is 1924 (terminal). The fork() return value is 2165 (child process PID).

After parent, child is executed and its has PID 2165. Since the parent process is terminated, the child process is taken care by root process "init"(1).

On success, fork() returns
1. PID of the child process in the parent process
2. 0 is returned in the child process
-----------------------------------------------------------------------------------------

There are few cases, we need to look at them very carefully.
Child Process terminated first
Parent process terminates first

The above example is for 2nd case, where parent process is terminated first.
The below example is for 1st case: Child process is terminated first.
-----------------------------------------------------------------------------------------
Example-2 
========

  1. #include<unistd.h>
  2. #include<stdio.h>

  3. #define CHILD 0

  4. int main()
  5. {
  6. pid_t child_pid;

  7. child_pid = fork();
  8. if (child_pid == CHILD) {
  9. /* child process */
  10. printf("child: my pid: %d..parent_pid: %d\n", getpid(), getppid());
  11. } else {
  12. /* parent process */
  13. printf("parent: my pid: %d\n", getpid());
  14. while(1);
  15. }
  16. return 0;
  17. }


Output:
=======
parent: my pid: 2244
child: my pid: 2245..parent_pid: 2244

Observation: ps -Af
===============
rrajk     2244  1924 86 09:47 pts/2    00:00:39 ./fork2
rrajk      2245  2244  0 09:47 pts/2    00:00:00 [fork2] <defunct>

Child process is done with its code execution. There is no code left to continue.
And, parent is still alive, child process is put into "defunc" state, until immediate parent process instructs kernel to destroy terminated process.
This child process is called as "Zombie Process".
------------------------------------------------------------------------------------------

We know that child process shares same address space with its parent process. If one process modifies the shared data then a new address space is allocated for that process. This concept is called Copy-On-Write approach.

The below example #3 will show, how copy-on-write approach works.
-------------------------------------------------------------------------------------------
Example-3
========

  1. #include<unistd.h>
  2. #include<stdio.h>
  3. #include<stdlib.h>

  4. #define CHILD 0

  5. int main()
  6. {
  7. pid_t child_pid;
  8. int k =10;

  9. child_pid = fork();
  10. if (child_pid == CHILD) {
  11. /* child process */
  12. printf("child: %d, parent: %d\n", getpid(), getppid());
  13. k = 44;
  14. printf("child: k value: %d\n", k);
  15.         } else {
  16. /* parent process */
  17. printf("parent: %d\n", getpid());
  18. wait(NULL);
  19. printf("parent: k value: %d\n", k);
  20. while(1);
  21. }
  22. return 0;
  23. }


output:
======
parent: 2124
child: 2125, parent: 2124
child: k value: 44
parent: k value: 10

observation:
===========
wait(): Suspends caller until child terminates and instructs the process manager to destroy child PCB that is in defunc (exit) state.
And, the value of k is not affected due to change in child process. Since either of the process modifies the shared values then copy-on-write procedure will takes place and new address space is created for that process.

If we observe, there is no child process with defunc status using "ps -Af" command.
rrajk      2134  2039 77 10:45 pts/0    00:00:09 ./fork3_wait
-------------------------------------------------------------------------------------------

Next: Synchronization of child and parent process execution
====

How famous companies got their names


Google: The name started as a joke boasting about the amount of information the search-engine would be able to search. It was originally named 'Googol', a word for the number represented by 1 followed by 100 zeros. After founders - Stanford graduate students Sergey Brin and Larry Page presented their project to an angel investor; they received a cheque made out to 'Google'. So, instead of returning the cheque for correction, they decided to change the name to Google.

Microsoft: Coined by Bill Gates to represent the company that was devoted to MICROcomputer SOFTware. Originally christened Micro-Soft, the '-' was removed later on.

LG: Combination of two popular Korean brands Lucky and Goldstar.
Linux: Linus Torvalds originally used the Minix OS on his system which here placed by his OS. Hence the working name was Linux (Linus' Minix). He thought the name to be too egotistical and planned to name it Freax (free+freak+x). His friend Ari Lemmke encouraged Linus to upload it to a network so it could be easily downloaded. Ari gave Linus a directory called 'Linux' on his FTP server, as he did not like the name Freax. (Linus parents named him after two-time Nobel Prize winner Linus Pauling).


Nike: Named for the greek goddess of victory. The swoosh symbolises her flight.

Skype: The original concept was ‘Sky-Peer-to-Peer’, which morphed into Skyper, then Skype.


Mercedes: This was actually financier's daughter's name.


Adidas: The company name was taken from its founder Adolf (ADI) Dassler whose first name was shortened to the nickname Adi. Together with first three letters of his surname it formed ADIDAS.


Adobe: This came from the name of the river Adobe Creek that ran behind the house of founder John Warnock.


Apple Computers: It was the favourite fruit of founder Steve Jobs. He was three months late for filing a name for the business, and he threatened to call his company Apple Computers if the other colleagues didn't suggest a better name by 5 o'clock.


CISCO: It is not an acronym as popularly believed. It's short for San Francisco.


Compaq: This name was formed by using COMP, for computer and PAQ to denote a small integral object.


Corel: The name was derived from the founder's name Dr. Michael Cowpland. It stands for COwpland Research Laboratory.


Hotmail: Founder Jack Smith got the idea of accessing e-mail via the web from a computer anywhere in the world. When Sabeer Bhatia came up with the business plan for the mail service, he tried all kinds of names ending in 'mail' and finally settled for hotmail as it included the letters "html" - the programming language used to write web pages. It was initially referred to as HoTMaiL with selective uppercasing.

Hewlett Packard: Bill Hewlett and Dave Packard tossed a coin to decide whether the company they founded would be called Hewlett-Packard or Packard-Hewlett.


Intel: Bob Noyce and Gordon Moore wanted to name their new company 'Moore Noyce' but that was already trademarked by a hotel chain so they had to settle for an acronym of INTegrated ELectronics.


Lotus (Notes): Mitch Kapor got the name for his company from 'The Lotus Position' or 'Padmasana'. Kapor used to be a teacher of transcendental Meditation of Maharishi Mahesh Yogi.


Motorola: Founder Paul Galvin came up with this name when his company started manufacturing radios for cars. The popular radio company at the time was called Victrola.

Sony: It originated from the Latin word 'sonus' meaning sound and 'sonny' as lang used by Americans to refer to a bright youngster.


SUN: Founded by 4 Stanford University buddies, SUN is the acronym for Stanford University Network. Andreas Bechtolsheim built a microcomputer; Vinod Khosla recruited him and Scott McNealy to manufacture computers based on it, and Bill Joy to develop a UNIX-based OS for the computer.


Apache: It got its name because its founders got started by applying patches to code written for NCSA's httpd daemon. The result was 'A PAtCHy' server - thus, the name Apache Jakarta (project from Apache): A project constituted by SUN and Apache to create a web server handling servlets and JSPs. Jakarta was name of the conference room at SUN where most of the meetings between SUN and Apache took place.


Tomcat: The servlet part of the Jakarta project. Tomcat was the code name for the JSDK 2.1 project inside SUN.


C: Dennis Ritchie improved on the B programming language and called it 'New B'. He later called it C. Earlier B was created by Ken Thompson as a revision of the Bon programming language (named after his wife Bonnie).


C++: Bjarne Stroustrup called his new language 'C with Classes' and then 'newC'. Because of which the original C began to be called 'old C' which was considered insulting to the C community. At this time Rick Mascitti suggested the name C++ as a successor to C.


GNU: A species of African antelope. Founder of the GNU project Richard Stallman liked the name because of the humour associated with its pronunciation and was also influenced by the children's song 'The Gnu Song' which is a song sung by a gnu. Also it fitted into the recursive acronym culture with 'GNU's Not Unix'.


Java: Originally called Oak by creator James Gosling, from the tree that stood outside his window, the programming team had to look for a substitute as there was no other language with the same name. Java was selected from a list of suggestions. It came from the name of the coffee that the programmers drank.


Mozilla: When Marc Andreessen, founder of Netscape, created a browser to replace Mosaic (also developed by him), it was named Mozilla (Mosaic-Killer, Godzilla). The marketing guys didn't like the name however and it was re-christened Netscape Navigator.

Red Hat: Company founder Marc Ewing was given the Cornell lacrosse team cap (with red and white stripes) while at college by his grandfather. He lost it and had to search for it desperately. The manual of the beta version of Red Hat Linux had an appeal to readers to return his Red Hat if found by anyone!


SAP: "Systems, Applications, Products in Data Processing", formed by 4 ex-IBM employees who used to work in the 'Systems/Applications/Projects' group of IBM.


UNIX: When Bell Labs pulled out of MULTICS (MULTiplexed Information and Computing System), which was originally a joint Bell/GE/MIT project, Ken Thompson and Dennis Ritchie of Bell Labs wrote a simpler version of the OS. They needed the OS to run the game 'Space War' which was compiled under MULTICS. It was called UNICS - UNIplexed operating and Computing System by Brian Kernighan. It was later shortened to UNIX.


SCO (UNIX): From Santa Cruz Operation. The company's office was in Santa Cruz.


Xerox: The inventor, Chestor Carlson, named his product trying to say 'dry' (as it was dry copying, markedly different from the then prevailing wet copying). The Greek root 'xer' means dry.


Yahoo: The word was invented by Jonathan Swift and used in his book 'Gulliver's Travels'. It represents a person who is repulsive in appearance and action and is barely human. Yahoo! founders Jerry Yang and David Filo selected the name because they considered themselves yahoos.


3M: Minnesota Mining and Manufacturing Company started off by mining the material corundum used to make sandpaper. It was changed to 3M when the company changed its focus to Innovative Products.

Tuesday, 6 August 2013

[Kernel Programming#6] Busy waiting & Delay of execution in Kernel

Busy waiting

The current execution of process can wait for some events should occur (like availability of required resources/data, passage of time or release of a lock). Here, the passage of times means delaying the current execution.
This waiting can be done in two ways
1.       Busy waiting
2.       Sleeping

Busy waiting

Here, the process/thread run in a loop by constantly checking the event has occurred condition. For example, if you want to wait for 5millisec then,
wait = getCurrentTime() + 5;
while(wait > getCurrentTime())
cpu_relax(); // do nothing
cpu_relax() is an architecture way of saying that there is no much work with CPU at this time.
This function does nothing.
The CPU cycles are being wasted for this amount of time. If the wait time is small then it is advisable to use the busy waiting concepts. Since, there is no overhead of context switching and performance is good.
But, if the wait time is more then it will be better to use sleeping concepts instead of busy waiting.

Sleeping

Here, the process/thread will be put into wait-queue so that CPU can start execution of other process/thread (using context switching). Kernel will wake up the process when the required condition for that process is met.
Advantage: There is no wastage of CPU cycles.
Overhead: context switching

Delaying the execution:

There are few scenarios where the current process has to wait for some period of time like for example h/w needs to accomplish few tasks. There are different techniques to achieve this delay.
We can divide delays into two types:
Long delays: Delays those are reliably longer than clock tick. It can use system clock for implementation.
Short delays: Implemented with s/w loops.
Long delays: below techniques can be used
è Busy waiting: cpu_relax()
è Release processor: schedule(). Releasing the CPU when the process doesn’t require it. There is a possibility of going to infinite sleep since CPU starts serving other process, and current sleep process may not get CPU in worst case. The above two approaches uses jiffi counter.
To avoid infinite sleep, another way is to ask the kernel to do this task like below.
è wait_event_timeout(): using this technique, the process can be wake up when somebody calls wake_up() and when the timeout expires.
But, If process specifically require to wake up with timeout value only then below technique will be used.
è Schedule_timeout():
Short Delays: techniques (Busy waiting)
ndelay(): set nano seconds delay. Optional.
udelay(): set micro seconds delay. Every architecture implements it.
mdelay(): set milli seconds delay. Optional.
Delay achieved and it is at least the value of delay and it could be more.
There are other techniques which doesn’t involve in busy waiting.
msleep(): puts the calling process in sleep.
msleep_interruptible(): puts the calling process in sleep.
ssleep(): --same—but in seconds.

Tuesday, 30 July 2013

Heap Memory concepts in C

Heap Memory

è Also called as dynamic memory, is an alternative to the local stack memory
Heap Memory
Local stack Memory
Manual allocation and deallocation
Programmer explicitly request the size of the memory needed
Automatic allocation and deallocation
Allocation à when function call
Deallocation à when function exists
Programmer has much greater control of memory
The blocks of memory can be requested of any size

More work

More bugs


The heap is an area of memory available to allocate areas ("blocks") of memory for the program.

Heap Manager:

Heap memory is managed by the library code called “heap manager”, used to keep track of the free blocks (available for use) and currently used blocks by the program and size of these blocks. The entire heap is free initially. Programmer requests block of memory to the Heap Manager by using library functions like malloc(), realloc() and calloc(). Heap memory can be freed by using free().
The prototypes of these functions are available in <stdlib.h>
The memory requests (memory allocation functions) like malloc() returns NULL pointer if the heap memory is full.

void* malloc(unsigned long size);
size
à requested size of the block in bytes
Returns pointer to the newly allocated heap block if successful.
Returns NULL if heap is full

void free(void* heapBlockPointer);
Takes argument as pointer to the heap block and returns this block to free pool for later re-use.


How allocation functions works? It requests block of memory in the heap of a particular size. The heap manager chooses a free block, and marks this area as “in use” in its private data structure, and returns a pointer to this heap block. And, heap manager will not allocate the same block to another request. Once the block is allocated, it is the owner responsibility to clear the old content in that block. We have one memory allocation function (calloc() in c) which sets the allocated blocks to all zeros.
Each allocation request reserves a contiguous area of the requested size in the heap and returns a pointer to that new block to the program.

The heap manager has its own, private data structures to record what areas of the heap are committed to what purpose at any moment the heap manager satisfies each allocation request from the pool of free memory and updates its private data structures to record which areas of the heap are in use.

How deallocation works? It is opposite to the allocation function. The owner makes deallocation request to return the heap block to the heap free area. The deallocation function takes the pointer to the heap block, which is returned by the allocation function. This pointer should be the same pointer returned earlier by the allocation function.

When the program is finished using a block of memory, it makes an explicit deallocation request to indicate to the heap manager that the program is now finished with that block.
The heap manager updates its private data structures to show that the area of memory occupied by the block is free again and so may be re-used to satisfy future allocation requests.

Memory Leaks:

If programmer forgets to deallocate the allocated heap memory then the program said to have a memory leak, that leads to abnormal behavior based on the allocation requests.
It is a serious problem if the program runs indeterminate amount of time, that results in continuous heap requests but there are no deallocation requests and the heap memory becomes full.

Garbage Collector


It takes over the most of the responsibility for Heap Management at the cost of little extra time taken at runtime. The programming lang like Perl and Java has the feature called Garbage Collector.

Tuesday, 23 July 2013

BootROM and Bootloader concepts

BootROM

Permanent code written on the Read Only Memory (ROM) of the Microcontroller, allow the device to Boot(Bootloader’s job) and Initialized all the peripherals, IOs and some hardware components.
Since it is written on read only memory, this code cannot be update or change.
It contains the very first code which is executed by the processor on power-on or reset. à Bootloader’s job is to find this code

Bootloader

>> BootROM contains the very first code which is executed by the processor on power-on or reset.
Bootloader is computer program which is responsible for finding and loading the final OS or a firmware which is supposed to run on the chip.

One main difference from BootROM is that it's usually in writable flash and can be replaced or upgraded.

Bootloader main task: load the kernel into RAM from flash memory.

Specifically, the boot loader was/is responsible for setting up an ATAG list that describing
the amount of RAM,
a kernel command line,
and other parameters.
One of the most important parameters is the machine type. With device trees, an entire description of the board is passed, in turn controlling the board only.

Since there is no standard mechanism for loading the OS (or first code), we use Bootloader to locate first code. This code can be found in flash memory, hard drives etc.
Bootloader is no longer present after it loads the OS.

Bootstrap loader

Bootloader: After power on , the Bootloader is controlling the board and does not rely on the linux kernel on any way.
Bootstrap loader:  performs checksum verification of the linux kernel and also does the decompression and relocation of the kernel to the system memory.

The bootstrap loader acts as a glue between the Bootloader and the linux kernel.

Tuesday, 16 July 2013

[Kernel Programming #5] Passing command line arguments to module

How to pass command line arguments to module.
We know argc/argv in C programming to pass command line arguments.

In kernel programming also, we have set of macros to do this task. They are,
module_param(name, type, permissions)
module_param_array(name, type, number_pointer, permissions)
and, we have other macros also, will discuss it later.
These macros are defined in <linux/moduleparam.h>.

Example: insmod module_2.ko variable_name=value, variable_name2=value

The argument name is the name of the variable declared in the module. The variables which we can define through command line option should be declared as global variable only. The name which we use in command line argument should match with the defined variable name in the module. Instead, we have another macro to set the name of the command line argument different from the variable name in the module.

module_param_named(command_line_var_name, actual_var_name, type, permissions)

The argument type is the type of the variable. It might be int, long, short, byte, uint, ulong, ushort, charp and bool.
charp: is used in case of string variable. The kernel copy and store the string passed by user in memory and points the actual variable to this memory.
Example:
static char *student_name;
module_param(student_name, charp, perm);

Instead, if we want to copy/store the string into the memory which is pointed by the actual variable then we can use another macro.

module_param_string(command_line_var_name, actual_var_name, len, permissions)
Example:
static char student_name[len];
module_param_string(studentname, student_name, len, perm);

The argument permissions is used to set read/write permissions for the variable.
Typical value would be 0644 (owner can read, write, group can read, everyone can read).

Kernel can also accepts the array by using the macro module_param_array.
The extra argument number_pointer is a pointer to an array_datatype in which the kernel stores the number of entries stored into the array.
Example:
static int students_marks[count];
static int marks;
module_param_array(students_marks, int, &marks, perm);

Program: module_param.c


  1. #include<linux/module.h>
  2. #include<linux/init.h>
  3. #include<linux/moduleparam.h>

  4. static int param_int = 999;
  5. static char *param_string = "KERNEL";
  6. static int param_array[3] = {-1,-1,-1};
  7. static int count = 0;
  8. static char param_string_len[10];

  9. module_param(param_int, int, 0);
  10. module_param(param_string, charp, 0);
  11. module_param_string(param_string_len, param_string_len, 10, 0);
  12. module_param_array(param_array, int, &count, 0);

  13. static int __init module_param_init(void) {
  14.         int i;

  15.         printk(KERN_INFO "param_int: %d\n", param_int);
  16.         printk(KERN_INFO "param_string: %s\n", param_string);
  17.         printk(KERN_INFO "param_string_len: %s\n", param_string_len);
  18.         for (i = 0; i < (sizeof(param_array)/sizeof(int)); i++)
  19.                 printk(KERN_INFO "param_array[%d]: %d\n", i, param_array[i]);

  20. return 0;
  21. }

  22. static void __exit module_param_exit(void) {
  23.         printk(KERN_INFO "module_param_exit:\n");
  24. }

  25. module_init(module_param_init);
  26. module_exit(module_param_exit);


Build: Please refer to previous posts to build the module, need to setup makefile.

Makefile for this program:
obj-m += module_param.o

KDIR = /usr/src/linux-headers-2.6.32-28-generic

all:
        $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
        rm -rf *.o *.ko *.mod.* *.symvers *.order

Experiment_1: insmod module_param.ko

Output: dmesg
[17046328.638809] param_int: 999
[17046328.638812] param_string: KERNEL
[17046328.638814] param_string_len:
[17046328.638816] param_array[0]: -1
[17046328.638818] param_array[1]: -1

[17046328.638819] param_array[2]: -1

Experiment_2: insmod module_param.ko param_int=111 param_string="PRACTICE" param_string_len="PEOPLE" param_array=11,22,33

Output: dmesg
[17047110.761552] param_int: 111
[17047110.761555] param_string: PRACTICE
[17047110.761557] param_string_len: PEOPLE
[17047110.761559] param_array[0]: 11
[17047110.761561] param_array[1]: 22
[17047110.761562] param_array[2]: 33

How to build the module, how to write makefile and how to insert module using insmod, and how to check the log ? Please refer the below posts for detailed explanation:

Reset/Recovery Ubuntu System Password

Ubuntu System Password recovery

We can reset the password (forgotten password) of your ubuntu system in FIVE simple steps.

Step1: Restart the system. Press Esc button when you see the message like "GRUB Loading ...". Then we will see the root shell window.

Step2: Select the recovery mode option in the root shell and then "Recovery menu" will be appeared on the screen then select "Drop to root shell prompt" option.

Step3: We will see a terminal
root@(none):/#
root@(none):/# passwd <user_name>

Example: If username of your system is hacker then please type passwd hacker and press enter.
Once you enter correct username, it is request you to set new password.
Please set your password.

Step4: Now, type sync and press enter
Step5: finally type reboot -f and press enter

You are now successfully reset your ubuntu system password.

You might also like

Related Posts Plugin for WordPress, Blogger...