Friday, July 9, 2010

Interview Questions on Functions

1. How to declare a pointer to a function?
Ans: int myFunc(); // The function
int (*fp)(); // pointer to the function.
fp = myFunc; // Assigning address of the function to the pointer.
(*fp)(); // Calling the function.
fp(); // Another way to call the function.

A function pointer is a pointer variable which holds the address of a function and used to invoke that function indirectly. The main use for function pointers is setting up "listener" or "callback" functions that are invoked when a particular event happens. The function is called and this notifies your code that something of interest has taken place. Sometimes user will click on a button or enter a test in the field. These operations are events that may require a response that your program needs to handle. How can your code known what happening? Using Call Back function. The user's click should cause the interface to call a function that you wrote to handle the event.
Ex: void click_button(int x, int y, const char *test, function callback_func);
Whenever the button clicked, callback_func will be invoked. Exactly what callback_func does depends on the button; this is why allowing the click_button function to take a function pointer is useful.

Syntax: void * (*foo) (int *); // Here *foo should refers to the function that returns void pointer and takes integer pointer as argument.

2. What is the use of function prototype?
Ans: The function prototype tells the compiler to expect a given function to be used in a given way. That is, it tells the compiler the nature of the parameters passed to the function (the quantity, type, order) and the nature of the value returned by the function.

3. What are the inline functions?
Ans: The inline comment is a request to the compiler to copy the code into the object at every place the function is called. That is, the function is expanding at each point of call. Most of the advantage of inline functions comes from avoiding the overhead of calling an actual function. Such overhead includes saving registers, setting up stack frames and so on. But with large functions the overhead becomes less important. Hence inline is a request not a command. Inlining tends to blow up the code size, because the function is expanding each point of call.

Syntax: inline int myFunc() { }

inline functions are not faster as compared to macros, but they kind of better than macros.
The problem with macros is it wont check syntax errors, and the code literally copies onto the location where it was called.
Ex: int i = 5; int i = 5;
int res = MULT(++i); int res = mult(++i);
macro is: MULT(a) a*a
inline is: inline int mult(int a) { return a*a; }

Macro expands, ++5 * ++5, so result would be 49 which is not expected.
While, inline expands, 6 * 6, so result would be 36 which is expected.

But, in some reasons inline can't prefer.
a) The function calls itself, that is recursive.
b) The function contains loop such as for(;;); or while();
c) The function size is too large.

4. How to variable argument list to a function?
Ans: printf is the best example for variable arguments. printf() is library function which declared int stdio.h. The declaration of printf is:
Syntax: int printf(const char *format, ...);

In order to access arguments within the called function, the functions declared in header file must be included. This introduces a new type called va_list and three functions that operate on objects of this type, called va_start, va_arg, and va_end.
Ex: printArgs(3, 45, 56, 67); // Call from main().
int printArgs(int numArgs, ...)
{
va_list ptr; va_start(ptr, numArgs); // Declare a pointer to arg list and initialized
for (int i = 0; i -lt numArgs; i++)
{
int arg = va_arg(ptr, int); // Retrieving arguments one by one.
printf("%d\n", arg);
}
va_end(ptr); // Set the pointer to point starting location for further use.
}

5. What are #pragmas?
Ans: Pragmas are special compiler commands which controls certain features of a compiler. Two problems arise when using pragmas.
a) Pragmas are compiler specific. You can't expect that one compiler will understand pragmas of other compile, even if both running on same machine.
b) You are not guaranteed that a compiler ignores pragmas, that he doesn't understand. Even more: It might not help, to some thing like this: #ifndef MY_COMPILER
#pragma DoAnything
#endif
A workaround is to put pragmas in a special include file.

The most common use is to tell the compiler about how to call library functions; Simple C functions expect their arguments on the stack, but library functions want their arguments in special processor registers.

6. Is ++i really faster than i = i + 1?
Ans: Any good compiler will and should generate identical code for ++i, i += 1, and i = i + 1; Compilers are meant to optimize the code. The programmer should not bother about such things. Also, it depends on the processor and compiler you are using. One needs to check the compiler's assembly language output, to see which one of the different approaches are better, if at all.

Note that speed comes good, well written algorithms and not from such silly tricks.

The reasons for using ++i or i += 1 or i = i +1 have to do with style, not efficiency.

7. What do mean lval and rval?
Ans: lvalue refers to the left hand side of an assignment expression. It must always evaluate to a memory location. rvalue represents the right side of an assignment expression; it may have any meaningful combination of variable and constant.

8. What is the purpose of typedef?
Ans: typedef is a keyword, used for to assign alternative names to existing data types.

A typedef can be used to simplify the declaration for a compound type(struct, union) or pointer type such as:
Ex: struct var {
int data1;
int data2;
char data3;
};
Here a struct var data type has been defined. To declare a variable of this type: struct var a;

A typedef can be used to eliminate the need for the struct keyword.
typedef struct var newtype;

We can now create a variable of this type with:
newtype a;

9. What is the difference between a deep copy and a shallow copy?
Ans: In object oriented programming, a type includes a collection of member fields. These fields may be stored either by value or by reference.

In shallow copy, a new instance of the type is created and the values are copied into the new instance. The reference pointers are also copied just like values. Therefore, the references are pointing to the original objects. Any changes to the members that are stored by reference appear in both the original and the copy, since no copy was made of the referenced object. Using a copy constructor, we simply copy the data values member by member.

In deep copy, the fields that are stored by value are copied as before, but pointers to objects stored by reference are not copied. Instead, a deep copy is made of the referenced object, and a pointer to the new object is stored. Any changes that are made to those referenced objects will not effect other copies of the object. The overloaded assignment operator would create a deep copy of objects.

10. If 'a' is an array, is a++ is valid?
Ans: No, We will get error message like, Lvalue required in function main().
Doing a++ is asking the compiler to change the base address of the array. This is only thing that the compiler remembers about the an array once its declared and it won't allow to change the base address. If it allows, it would be unable to remember the beginning of the array.

11. What is storage class?
Ans: This is part of variable declaration that tells the compiler how to interpret the variable's symbol. It does't itself allocate storage, but usually tells the compiler how the variables should be stored. Only one storage class specifiers is permitted in a declaration. If you omit the storage class in the declaration, then default storage class would consider. For outside declaration, the default storage class is extern. For inside declaration, auto. The only exception to this rule is the declaration of functions, whose default storage class specifier is always extern.

Some storage classes in C are:
a) auto: Local variables.
b) static: Static variables are defined in a non-volatile memory such that they retain their contents throughout the program's execution.
c) register: Ask the compiler to devote a processor register to this variable in order to speed the program's execution.
d) extern: tells the compiler that the variable is defined in another module.

12. What is the difference between const and #define?
Ans: #define ABC 5
const int abc = 5;

There are two main advantages of the second statement over first.
a) The type of the constant is defined. This allows for some type checking by the compiler. For #define, there is no type.
b) The constants are variables with definite scope. But, #define are global scope.

13. What is structure padding?
Ans: Most processors require specific memory alignment on variables certain types. char variable can be byte aligned and appear at any byte boundary. short variable must be 2 bytes, they can appear at any even byte boundary. This means that 0x123 is not valid location for short, 0x122 is valid location. int variable must be 4 bytes, they can appear any byte boundaries that are multiple of 4 bytes. This means that 0x122 is not memory location for int, 0x124 is valid location.
Ex: struct myStruct {
char a; // 1-byte size
short b; // 2-bytes size
int c; // 4 bytes size
};
If we sum bytes of inside variables in the structure, the value would be 7, but not.
If you assume base memory location for this structure is 0x100.
0x100 - char
0x101 - hole
0x102 and 0x103 - short
0x104-0x107 - int

So, total size of this structure is 8. Padding enables the CPU to access the members faster.

14. What are bit fields in structures?
Ans: Because of padding in structures, some memory holes observed. To avoid wastage of memory in structures, a group of bits can be packed together into an integer and its called a bit field.
Ex: struct student {
char name[30]; // 30-bytes memory
unsigned sex:1; // 1 bit
unsigned age:3; // 3 bits
unsigned rollNo:7; // 7 bits
unsigned branch:2; // 2 bits.
}my;
but, size of this structure is 32 bytes.

There are some limitations with respect to these bit fields, however
a) Cannot scanf() directly into bit fields. Ex: scanf(%d", my.age);
b) Pointers cannot be used on bit fields to access them.
c) Cannot have an array of bit fields.

The main use of bit fields is either to allow tight packing of data or to be able to specify the fields within some externally produced data files.

15. What is union?
Ans: Union is just like a structure contain members whose individual data types may differ from one another. However the members that compose a union all share same storage area within the computers memory whereas each member within a structure us assigned its own unique storage area. Thus unions can save memory if you have a group of data where only one of the type is used at a time. The size of union is equal to the size of it's largest data member. The C compiler allocates just enough space for the largest member. This is because only one member can be used at a time, so the size of the largest is sufficient for all.
Ex: union time {
long simpleTime;
double preciseTime;
} myTime;
The union above could be used to either store the current time in seconds or store the accurate time in milliseconds.

16. What is token pasting operator and stringing operator?
Ans: Token pasting operator is ##.
Ex: #define f(g1,g2) g1##g2
main() {
int var12 = 12;
printf(%d", f(var,12));
}
Output is 12. ## will concatenate strings.

Stringing operator is #
Ex: #define sum(x,y) printf(#xy "=%f\n", xy)
main() {
sum(a+b); // As good as printf("a+b = %f\n", a+b);
}

17. How do stat(), fstat() and vstat() work?
Ans: These functions are used to get the file status.

stat(const char *file_name, struct stat *buff);
- states the file pointed by file_name and fills in buff

fstat(int file_desc, struct stat *buff);
- identical to stat, only open file pointed by file_desc is stat-ed in place of place of file_name.

lstat(const char *file_name, struct stat *buff);
- identical to stat, except in case of a symbolic link, where the link itself is stat-ed, not the file that it refers to.

On success, zero is returned. On error, -1 is returned.

Use function like stat() to find out if a file exist or not. Also, one can open fopen(). When using fopen(), just open for reading and close immediately. If the file does't exist, fopen() will given an error.

18. What are the file related functions?
Ans:
a) fopen: FILE * fopen(const char * filename, const char * mode);
Open the file whose name is specified in the parameter filename and associates it with a stream that can be identified in future operations by the FILE objects whose pointer is returned. The operations that are allowed on the steam and how these performed are defined by the mode parameter. Modes are "r" for read, "w" for write, "a" for append, "r+" for both reading and writing(existing file), "w+" for both reading and writing(new file) and "a+" for reading and appending.

b) fclose: int fclose(FILE *stream);
Closes the file associated with the stream and disassociates it. All internal buffers associated with it are flushed. Even if the call fails, the stream passed as parameter will no longer be associated with the file. On success, zero value is returned, on failure EOF is returned.

c) fprintf: int fprintf(FILE * stream, const char * format, ...);
Writes to the specified stream a sequence of the data formatted as the format argument specifies. After the format parameter, the function expects at least as many additional arguments as specified in format.

d) fscanf: int fscanf(FILE * stream, const * format, ... );
Reads data from the stream and stores the according to the parameter format into the locations pointed by the additional arguments.

e) getc: int getc(FILE * stream);
Get character from stream. Returns the character currently pointed by the internal file position indicator of the specified stream. The internal file position indicator is then advanced by one character to point to the next character.getc is equivalent to fgetc, but getc may be implemented as a macro, so the argument passed to it should be an expression with potential side effects. getchar() is similar function without stream parameter.

f) putc: int putc(int character, FILE * stream);
The character is written at the current position of the stream as indicated by the internal position indicator, which is then advanced one character. pu
tc is equivalent to fputc, but getc may be implemented as a macro, so the argument passed to it should be an expression with potential side effects. putchar() is similar function without stream parameter.

g) feof: int feof(FILE * stream);
Checks whether the End-of-File indicator associated with stream is set, returning a different from zero if it is. This indicator is generally set by a previous operation on the stream that reached the End-of-File.

h) fseek: int fseek(FILE * stream, long int offset, int origin);
Set the position indicator associated with the stream to a new position defined by adding offset to a reference position specified by origin. The End-of-File internal indicator of the stream is cleared after a call to this function and all effects from previous calls to ungetc are dropped. Possible origins are
SEEK_SET - Beginning of the file
SEEK_CUR - Current position of the file pointer
SEEK_END - End of the file.

i) rewind: void rewind(FILE * stream);
Set the position indicator associated with stream to the beginning of the file. A call to rewind is equivalent to:
fseek(stream, 0L, SEEK_SET);
Except that, unlike fseek, rewind clears the error indicator.
On streams open for update (read+write), a call to rewind allows to switch between reading and writing.

j) fgetpos: int fgetpos(FILE * stream, fpos_t * pos);
Gets the information needed to uniquely identify the current value of the stream's position indicator and stores it in the location pointed by position. The parameter position should point to an already allocated object of the type fpos_t, which is only intended to be used as a parameter in future calls to fputpos.

k) fsetpos: int fsetpos(FILE * stream, const fpos_t * pos);
Changes the internal file position indicator associated with stream to a new position. The position parameter is a pointer to an fpos_t object whose value shall have been previously obtained with a call to fgetpos.

l) fread: size_t fread(void * ptr, size_t size, size_t count, FILE * stream);
Reads an array of count elements, each one with a size of size bytes, from the steam and stores them in the block of memory specified by ptr. The position indicator of the stream is advanced by the total amount of bytes read. The total amount of bytes read if successful is (size * count).

m) fwrite: size_t fwrite(const void * ptr, size_t size, size_t count, FILE * stream);
Writes an array of count elements, each one with a size of size bytes, from the block of memory pointed by ptr to the current position in the steam. The position indicator of the stream is advanced by the total number of bytes written. The total amount of bytes written is (size*count).

n) fgets: char * fgets(char * str, int num, FILE * stream);
Reads characters from stream and stores them as a C string into str until(num-1) characters have been read or either a newline or the end-of-file is reached, whichever comes first. A newline character makes fgets stop reading, but it is considered a valid character and therefore it is included in the string copied to str. A null character is automatically appended in str after the characters read to signal the end of the C string.

o) fputs: int fputs(const char * str, FILE * stream);
Writes the string pointed by str to the stream. The function begins copying from the address specified(str) until it reaches the terminating null character('\0'). This final null-character is not copied to the stream.

Interview Questions on Pointers

1. What does *p++ and ++*p do?
Ans: "++" has higher precedence than "*", hence in case of *p++, pointer would be incremented and return the value of new pointer value. In case of ++*p, the value which is pointed by p will be incremented.

2. What is NULL pointer? How is it different from uninitialized pointer?
Ans: NULL pointer is a pointer which is not pointing any thing in the memory. NULL is defined as
(void*)0.
Uninitialized pointer is pointing some memory location but the pointer values are not assigned.

3. What is a NULL pointer assignment error?
Ans: When we initialize any pointer to NULL means that it doesn't point anything. Now If we are trying to access or put some value in it then the error NULL pointer assignment occurs usually "Segmentation Fault".
EX: int *p;
*p = 12;

4. What is the difference between arr and &arr?
Ans: arr is pointer to the first element of the array and &arr is pointer to the entire array.

5. Is the cast to malloc() required at all?
Ans: malloc() returns pointer to void. That is, pointer to the first memory location of the allocated memory block. The pointer type is unknown at this point, hence typecasting is done later. void pointer is generic pointer anyway.
Ex: int *myarray;
myarray = (int*)malloc(numberOfElements * sizeof(int));

6. What does malloc(), calloc(), realloc(), and free() do?
Ans: malloc() is a memory manager, used to allocate memory block.
Syntax:
void* malloc(size_t size); //size_t is unsigned integer.
This allocates a block of size bytes of memory, return a pointer to the beginning of the block. The content of newly allocated memory is not initialized, hence garbage values would be there.

calloc() is also used to allocate space for array in memory.
Syntax:
void * calloc(size_t num, size_t size);
This allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all bits to zero. Which is equivalent to p = malloc(m*n); memset(p, 0, m*n);

realloc() is used to reallocate memory block.
Syntax:
void * realloc(void * ptr, size_t size);
The size of the memory block pointed to by the ptr parameter is changed to the size bytes, expanding or reducing the amount of memory available in the block. If the new size is more than old size, then newly allocated data would have garbage values. Otherwise, data would be remain. It is same as malloc()

free() is deallocate space in memory.
Syntax: void free(void * ptr);
A block of memory previously allocated by malloc, calloc, realloc is deallocated, making it available again. This function leaves the value of ptr unchanged, hence it still points to the same location, and not to the NULL pointer.

It is better to set the pointer to NULL after freed it to prevent accidental usage. You can't use dynamically-allocated memory after free it.

There was no standard to find out how big the allocated memory block is using the pointer.

7. What is the difference between const char *p, char * const p and const char * const p?
Ans: const char *p:- This is a pointer to constant char. One cannot change the value pointed by p, but can change the pointer p itself. char const *p is also same.
Ex: *p = "A"; // is illegal.
p = "Hello"; // is legal.

char * const p:- This is a constant pointer to (not-const)char. One cannot change the pointer p, but can change the value pointed by p.
Ex: *p = "A"; // is illegal.
p = "Hello"; // is legal.

const char * const p:- This is a constant pointer to constant char. One cannot change either pointer or value pointed by p.
Ex: *p = "A"; // is illegal.
p = "Hello"; // is illegal.

8. What is a void pointer? Why can't we perform arithmetic on a void * pointer?
Ans: A void data type is used when no other data type is appropriate. A void pointer is a pointer that may point any kind of object. It is used when a pointer must be specified but its type is unknown. The compiler doesn't know the size of the objects in case of void * pointer. Before performing arithmetic, convert the pointer either to char * or to the pointer type you are trying to manipulate.

9. What do Segmentation Fault, access violation, core dump and bus error mean?
Ans: Segmentation Fault, core dump, bus error kind of errors usually mean that the program tried to access memory it doest't have.

Probable causes are overflow of local arrays, improper use of NULL pointers, corruption of the malloc() data structures.

SIGSEGV indicates an invalid access to valid memory address. SIGBUS indicates an access to invalid memory address.

Segmentation fault occurs a process tries to access memory that it is not allowed to, such as the memory at address 0(where NULL points). It is easy to get to a segment fault which dereference NULL.
Ex: char *p;
p = NULL;
++(*p);

10. What is the difference between an array of pointers and a pointer to an array?
Ans: int *p[10]; // array of 10 pointers
int (*p)[10]; // pointer to a 10 elements array

11. What is memory leak?
Ans: Some programs fail to release memory that in no longer being used back inti the pool of available memory. The result is that the used memory is not cleared for use by other programs and thus diminishes the operating capacity of the computer.
Ex: while(malloc(50)); // Here 50 bytes of memory block will be allocated in infinite times. It will return NULL sooner or later due to lack of memory.

12. What is dangling pointer?
Ans: Dangling pointer arise when an object is deleted or deallocated, without modifying the value of pointer, so the pointer still points to the memory location of the deallocated memory. Dereferencing such a pointer usually produces garbage.
Ex: {
char *dp = NULL;
{
char c;
dp = &c;
} // c falls out of the scope
} // dp is now a dangling pointer

The solution to this problem would be to assign NULL to dp immediately before the inner block is exited.
Ex: char *ch = (char*)malloc(sizeof(char));
free(dp); //dp is now became a dangling pointer
dp = NULL; //dp is no longer dangling

Using reference counters which keep track of how many pointers are pointing to this memory location can prevent such issues. The reference counts are incremented when a new pointer starts to point to the memory location and decremented when they no longer need to point to that memory. When the reference count reaches zero, the memory can be safely freed. Also, once freed, the corresponding pointer must be set to NULL.

13. What is equivalent to a[i], and a[i][j]?
Ans: a[i] == i[a] == *(a+i) == *(i+a)
a[i][j] == *(*(a+i)+j)

14. What operations are valid on pointers?
Ans: (px <> py), (px >= py), (px <= py), (px != py), (px == py), px = px + n,
px = px - n, px - py.
Other than these, all are invalid (multiplication, division, addition of two pointers).

15. What are near, far and huge pointers?
Ans: A near pointer is 2 bytes long whereas a far and a huge pointers are 4 bytes long. near, far, and huge pointers exist only under DOS. Under Windows and Linux every pointer is 4 bytes long.

A far pointer and huge pointer are always treated as 32-bit pointer and contain both segment and an offset. But only difference is huge pointer is normalized pointer whereas far pointer is not.
Ex: char far *a = 0x00000120; char far *b = 0x00120000;
char huge *a = 0x00000120; char huge *b = 0x00120000;

In case of far pointer, all 32 bits are in consideration, hence both address are different, but not. In case of huge pointer, all 32 bits are converted into 20-bits towards normalization. Hence both address are referring same location as bellow.
00000 00120 // segment address left shifted by 4bits.
0120 0000 // offset address
00120 00120 // normalized 20-bit address.

16. What is the difference between a null pointer, a NULL macro, the ASCII NUL character and a null string?
Ans: A null pointer is a pointer, which does't point anywhere.

A NULL macro is used to represent the null pointer in source code. It has a value 0 associated with it.

The ASCII NUL character has all its bits as 0 but does't have any relationship with the null pointer.

The null string is just another name for an empty string ""

17. What is the difference between malloc() and calloc()?
Ans: void * malloc(size_t size);
void * calloc(size_t num, size_t size);
Functionality wise both are same that they allocate memory from a storage pool which is heap. Both are memory managers not memory allocators. Memory allocation is done by OS by brk() and sbrk().

Some of differences between malloc() and calloc() are:
a) malloc() takes one argument, and calloc() takes two arguments.
b) calloc() initializes all bits to zero, but malloc() does not.
c) A call to calloc() is equalent to a call to malloc followed by one memset(). calloc() is equivalent to
p = malloc(m*n);
memset(p, 0, m*n);
d) Since calloc() is single call to allocate and initialize, it is faster compare to malloc() and memset().

18. Why sizeof() an operator and not a function?
Ans: sizeof() is a compile time operator. To calculate size of an object, we need the type information. This type information is available only at compile time. The compiler replaces all sizeof calls or operations with the actual size_t value.

A function would be pointless since the discovery of types and their sizes is done at compile time. Now in cases where the size of something needs to be known at run time!!!

19. What is an opaque pointer?
Ans: A pointer is said to be opaque if the definition of the type to which it points to is not included in the current translation unit. A translation unit is the result of merging an implementation file with all its headers and header files.

20. What are the common causes of pointer bugs?
Ans: Uninitialized pointers- One of the easiest way to create a pointer bug is to try to reference the value of a pointer even though the pointer is uninitiated and doest not yet to point to a valid address. Ex: int *p; *p = 12;
In this case, p is points to random memory location.
So, make sure you initialize all pointers to a valid address before deference them.

Invalid pointer references- Occurs when a pointer's value is referenced even though the pointer doesn't point to a valid block.
Ex: p = q; // Here q is uninitialized, then the pointer p will then become uninitialized as well and any reference to *p is an invalid pointer reference.

Zero Pointer Reference- Occurs whenever a pointer pointing to zero is used in a statement that attempts to reference a block.
Ex: p = 0; *p = 12; // There is no block pointed by p.

Interview Questions in Operating Systems

1. What is a process?
Ans: A process is a program which is being executed. There are two mode in process execution: a) user mode and b) kernel mode. Normally, a process executes in the user mode. When a process executes a system call, then the mode of execution changes from user mode to kernel mode.

2. What is scheduling? and type of scheduling?
Ans: On most multitasking systems, only one process can truly active at a time, the system must therefore share its time between the execution of many processes. This time sharing is called Scheduling. There are mainly two types of scheduling.
a) Queuing: This approach for serial or batch jobs like print pooling and request from a server. There are two main ways of giving priority to the jobs in a queue. First Come First Serve(FCFS/FIFO), and Shortest Job First(SJF).

b) Round-robin: In this approach several tasks can co-exist. The scheduler gives a short time-slice to each job, before moving on to the next job, polling each task round and robin. This way, all the tasks advance little by little on a controlled basis.

3. What is Zombie process and Orphan Process?
Ans: On UNIX, a zombie process or defunct process is a process that has completed execution but still has an entry in the process table, allowing the process that started it to read its exit status. Simply, the child process has died but has not yet been reaped.

When a process end, all of the memory and resources associated with it are deallocated so they can be used by other processes, but in this case not because this process entry in the process table. When child ends, parent gets SIGCHLD signal indicating that a child has died, the handler for this signal will typically execute the wait system call, which reads the exit status and remove zombies. If parent ignores the SIGCHLD signal, the zombie will be left in the process table.

If zombie exist for more than a short period of time typically indicate a bug in the parent program. To remove zombies from the system, the SIGCHLD signal can be sent to the parent manually, using kill command. If the parent still refuses, the next step would be remove the parent process. When a process losses its parent, init becomes its new parent, init periodically executes the wait system call to reap any zombies with init as parent.

An Orphan is a process whose parent process has finished or terminated.

4. What is fork(), exec(), wait(), and waitpid()? What is the difference between fork() and vfork()?
Ans: Fork() is used to create a new process. It doesn't take any arguments and returns a process ID. If fork() returns negative number the creation of child process was unsuccessful. A call to fork() returns a zero to newly created child process and the same call to fork() returns a positive number(child process ID) to the parent. Both parent and child process have identical but separate address space.

"init" process is the very first process run upon startup. There are two commands to set the process's priority nice and renice.

exec() functions replaces a current process with another according to the arguments given.

wait() can be used to determine when a child process has completed it's job and finished. wait() causes a parent process to pause until a child process dies or finished. The call returns the PID of the child process for which status information is available.

waitpid() is a system call that can be used to wait fir child process. This call however can be used to wait for specific process to terminate.

The difference between fork() and vfork(): vfork() is a low overhead version of fork(), as fork() involves copying the entire address space of the process and is therefore quite expensive. The basic difference between the two is that when a new process is created with vfork(), the parent process is temporarily suspended, and the child process might borrow the parent's address space. This strange state of affairs continues until the child process either exits, or calls execve(), at which point the parent process continues.

5. What is context switching?
Ans: Switching from one running process to another running process incurs a cost to the system. The values of all the registers must be saved in the present state, the status of all opened files must be recorded and the present position of the program must be recorded. Then the contents of the MMU must be stored for the process. Then all those things must be read in for the next process, so the state of the system is exactly as it was when the scheduler last interrupted the process. This is called context switching.

The state of each process is saved to a data structure in the kernel called process control block(PCB).

6. What are the process states?
Ans: The state of process may be one of the following:
a) New
b) Ready (in line to be executed)
c) Running (active)
d) Waiting (sleeping, suspended)
e) Terminated (defunct)

7. What is the difference between process and Thread?
Ans: Major differences are between process and thread are:
a) Process is Heavy Weight Process, because the context switching between processes is more expensive. It will take more time from one memory location to other memory location. Thread is Light Weight Process since the context switching between threads is less expensive rather than process. Threads are shared their memory location.

b) Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.

c) Threads can directly communicate with other threads of its process; process must use inter-process communication to communicate with other processes.

d) Threads have almost no overhead; processes have considerable overhead.

8. What is deadlock and possible occurances?
Ans: Deadlock occurs when a number of processes are waiting for an event which can only be caused by another of the waiting process.

These are the essential requirements for a deadlock:
a) Circular Wait: Two or more processes form a circular chain where each process waits for a resource that the next process in the chain holds.

b) Mutual Exclusion: A resource that can't be used by more than one process at a time.

c) No Preemption: The process can't be forced to give up the resources they are holding. Resources can be released only by the explicit action of the process.

d) Hold and Wait: Process already holding a resources may request new resources.

9. What is semaphore?
Ans: A semaphore is a flag which can have a more general value than just true or false. A semaphore is like integer. When you create a semaphore, you can initialize its value to any value to any integer, but after that only operations you are allowed to perform are increment and decrement, but you can't read current value of the semaphore.

When a thread decrements the semaphore, if the result is negative, the thread blocks itself and can't continue until another thread increments the semaphore.

When a thread increments the semaphore, if there are other threads waiting, one of the waiting threads gets unblocked.

10. What is belady's Anomaly?
Ans: It is also called FIFO anomaly because this occurs in case of the FIFO page replacement policy in the OS. Usually, on increasing number of frames allocated to a process's virtual memory, the process execution is faster, because fewer page faults occur. Sometimes revers happens, i.e., the execution time increases even when more frames are allocated to the process.

This does't occur in the LRU(least recently used) scheduling algorithm.

11. What is Translation Look-aside Buffer(TLB)?
Ans: It is a CPU cache that memory management hardware uses to improve virtual address translation speed. A TLB has a fixed number of slots that contain page table entries, which maps virtual addresses to physical addresses.

12. What is busy-waiting?
Ans: The repeated execution of a loop of code while waiting for an event to occur is called busy-waiting. The CPU is not engaged in any real productive activity during this period, and the process does't process towards completion.

13. What is paging? What is page fault? What is demand paging?
Ans: It is one of the memory management scheme which used by operating system to store and retrieve data from secondary storage for use in main memory. In Paging, OS retrieves data from secondary storage in same-size blocks called pages. Main advantage is that it allows the physical address space of a process to be non-contiguous, so this avoids storage and fragmentation problems.

When a program tries to access pages those are not currently mapped to physical address(RAM) is called page fault.

The OS copies a disk pages into physical memory only if the executing process demands them is called Demand paging.

14. What are local and global page replacements?
Ans: Page replacement algorithm can be local or global.
When a process incurs a page fault, local page replacements algorithm selects for replacement some page that belongs to the same process, where as global replacement algorithm is free to select any page in memory.

15. What is cause of thrashing?
Ans: Thrashing is caused by under allocation of the minimum number of pages required by a process, forcing it to continuously page fault. The system can detect thrashing by evaluating the level of CPU utilization as compared to the level of multiprogramming. It can be eliminated by reducing the level of multiprogramming.

To resolve thrashing due to excessive paging, a user can do any of the following:
a) Increase the amount of RAM in the computer (long-term solution)
b) Decrease the number of programs being run on the computer.
c) Replace programs that are memory-heavy with equivalents that use less memory.

16. What is the difference between volatile and non-volatile memory?
Ans: Volatile Memory - They loss the information when not powered. Ex. RAM means temporary memory.
Non-Volatile Memory - They don't loss the information when not powered. Ex: ROM means permanent memory.

17. What is segmentation fault?
Ans: When a program attempts to access a memory location that is not allowed to access, or attempts to access a memory location in a way that is not allowed, for example- attempting to write to a read-only location.
Ex: char c* = "Hello";
*c = 'h';

18. What is fragmentation? What are the types of fragmentation?
Ans: Fragmentation occurs in a dynamic memory allocation system when many of the free blocks are too small to satisfy any request.

There are three types of fragmentation:
a) Internal Fragmentation: The term "internal" refers to the fact that the unusable storage is inside the allocated region but is not being used. Internal fragmentation is the space wasted inside of allocated memory blocks because of restriction on the allowed sizes of allocated blocks. Allocated memory may be slightly larger than requested memory; this size difference is memory internal to a partition, but not being used.

b) External Fragmentation: The term "external" refers to the fact that the unusable storage is outside of the allocated regions. This fragmentation happens when a dynamic memory allocation algorithm allocates some memory and small piece is left over that cannot be effectively used. If too much external fragmentation occurs, the amount of usable memory is drastically reduced. Total memory space exists to satisfy a request, but it is not contiguous. External fragmentation also occurs in file systems as many files of different file sizes are created, change size and are deleted. This effect is even more worse if a file which is divided into many small pieces is deleted, because this leaves similarly small regions of free spaces.

19. What is de-fragmentation?
Ans: De-fragmentation is a process that reduces the amount of fragmentation in file system. It does this by physical organizing the contents of the disk to store the pieces of each file close together and contiguously. It also attempts to create larger regions of free space using compaction. to impede the return of fragmentation.

20. What is compaction?
Ans: Compaction refers to the mechanism of shuffling the memory portions such that all the free portions of the memory can be aligned or merged together in a single large block. To overcome the problem of fragmentation, either internal or external, performs this mechanism frequently. Compaction is possible only if relocation is dynamic and done at run-time. If relocation is static and done at assembly or load-time, compaction is not possible.