Unix Programming - Module 3
Unix Programming - Module 3
Module 3:
(a). Describe how a c program is started and various ways it terminates.
Ans: PROCESS TERMINATION:
There are eight ways for a process to terminate.
1. Normal termination occurs in five ways:
✓ When a C program is executed by the kernel—by one of the exec functions a special
start-up routine is called before the main function is called.
✓ The executable program file specifies this routine as the starting address for the
program; this is set up by the link editor when it is invoked by the C compiler.
✓ This start-up routine takes values from the kernel—the command-line arguments
and the environment—and sets things up so that the main function is called.
The exit handlers are:
a) exit:
✓ exit function terminates the process normally, performs certain cleanup processing
and then returns to the kernel.
✓ the exit function has always performed a clean shutdown of the standard I/O
library: the fclose function is called for all open streams. This causes all buffered output
data to be flushed (written to the file).
✓ _exit and _Exit functions terminate the process normally and return to the kernel
immediately
All three exit functions expect a single integer argument, called the exit status.
The exit status of the process is undefined if
✓ With ISO C, a process can register up to 32 functions that are automatically called by
exit. These are called exit handlers and are registered by calling the atexit function.
✓ Prototype: #include <stdlib.h>
int atexit(void (*func)(void)); Returns: 0 if
OK, nonzero on error
▪ Text segment, the machine instructions that the CPU executes. Usually, the text segment is
sharable so that only a single copy needs to be in memory for frequently executed programs,
such as text editors, the C compiler, the shells, and so on. Also, the text segment is often read-
only, to prevent a program from accidentally modifying its instructions.
• Initialized data segment, usually called simply the data segment, containing variables that are
specifically initialized in the program.
For example, the C declaration int
maxcount = 99;
appearing outside any function causes this variable to be stored in the initialized data segment
with its initial value.
• Uninitialized data segment, often called the "bss" segment, named after an ancient assembler
operator that stood for "block started by symbol." Data in this segment is initialized by the kernel
to arithmetic 0 or null pointers before the program starts executing. The C declaration long
sum[1000];
appearing outside any function causes this variable to be stored in the uninitialized data
segment.
• Stack, where automatic variables are stored, along with information that is saved each time a
function is called. Each time a function is called, the address of where to return to and certain
information about the caller's environment, such as some of the machine registers, are saved on
the stack. The newly called function then allocates room on the stack for its automatic and
temporary variables. This is how recursive functions in C can work. Each time a recursive function
calls itself, a new stack frame is used, so one set of variables doesn't interfere with the variables
from another instance of the function.
• Heap, where dynamic memory allocation usually takes place. Historically, the heap has been
located between the uninitialized data and the stack.
(c). Describe general unix file API’s with syntax and explain the each field
in detail.
Ans: In UNIX everything can be treated as files. Hence files are building blocks of UNIX
operating system. When you execute a command in UNIX, the UNIX kernel fetches the
corresponding executable file from a file system, loads its instruction text to memory and
creates a process to execute the command.
Link Files (only in UNIX) Example: alias names of a file, Shortcuts in Windows.
Regular files
➢
It is a text or binary file.
➢
These files may be read or written by users with the appropriate access permission.
➢
For Example: All exe files, text, Document files and program files. Created and modified
by using editors (vi, vim, emacs) or by compilers (cc, gcc, c++,g++).
➢
And these files are removed by using rm command.
Directory files
➢
A directory is like a file folder that contains other files, including other subdirectories.
➢
It provides a means for users to organize their files into some hierarchical structure based
on file relationship or users.
➢
mkdir is the command used for creating the directory.
➢
mkdir newdir // creates an empty directory newdir under the current directory.
➢
An unix directory is consider to be an empty if it contains no other files except . and ..
files.
➢
rmdir is a command, which is used to delete a directory(s).
➢
rmdir newdir // To remove the directory that directory should be empty.
➢
The contents of a directory files may be displayed in UNIX by the ls command.
Device files
➢
These are physical devices such as printers, tapes, floppy devices CDROMs, hard disks and
terminals.
➢
There are two types of device files: Block and Character device files.
a. Block Device files:
➢
A physical device that transmits block of data at a time.
➢
For example: floppy devices CDROMs, hard disks.
b. Character Device files:
➢
A physical device that transmits data character by character. For example: Line
printers, modems etc.
➢
mknod is the command used for creating the device files.
Syntax: $mknod Device_Filename DeviceFile_Type Major_Number Minor_Number
Example1: # mknod /dev/cdsk c 120 20
This creates character device file called cdsk with major number 120 and minor
number 20.
Example2: # mknod /dev/bdsk b 225 15
This creates block device file called bdsk with major number 225 and minor number 15.
➢
A major device number is an index to a kernel table that contains the addresses of all
device driver functions known to the system.
➢
A minor device number is an integer value to be passed as an argument to a device
driver function when it is called.
➢
The minor device number tells the device driver function what actual physical device
it is taking to and the input output buffering scheme to be used for data transfer.
➢
In UNIX, mknod must be invoked through superuser privileges.
FIFO file
➢
It is a special pipe device file, which provides a temporary buffer for two or more
processes to communicate by writing data to and reading data from the buffer.
➢
A process may write more than PIPE_BUF bytes of data to a FIFO file, but it may be
blocked when the file buffer is filled.
➢
In this case the process must wait for a reader process to read data from the pipe and
make room for the write operation to complete.
➢
Finally, the data in the buffer is accessed in a by a first-in-first-out manner, hence the
file is called a FIFO.
➢
These are having name hence they called named pipes.
➢
The size of the buffer associated with FIFO file is fixed to PIPE_BUF or
_POSIX_PIPE_BUF.
➢
mkfifo is the command used for creating a FIFO file(s). mkfifo /usr/prog/fifo_pipe or
by using mknod with the option p mknod /usr/prog/fifo_pipe p
➢
rm is the command used for removing FIFO files.
Symbolic Link files
➢
A symbolic link file contains a path name which references another file in either the
local or a remote file system.
➢
These are not supported by POSIX.1
➢
A symbolic link may be created in UNIX via the ln command.
➢
This command creates a symbolic link /usr/csr/unix which references the file
/usr/yuktha/original. The cat command which follows will print the content of the
/usr/yuktha/original file:
➢
Example: ln –s /usr/yuktha/original /usr/csr/unix cat -n /usr/csr/unix ➢ It is possible to
create a symbolic link to reference another symbolic link.
➢
rm, mv and chmod commands will operate only on the symbolic link arguments
directly and not on the files that they reference.
fork(): Creates a child process. A new process is created because an existing process
creates an exact copy of itself. This child process has the same environment as its
parent but only the PID is different. This procedure is known as forking.
exec(): After forking the process, the address space of the child process is overwritten
by the new process data. This is done through exec call to the system. No new process
is created over here. The PID & PPID remains unchanged.
wait(): The parent then executes wait system call to wait for the child process to
complete its execution.
Prototype: #include<unistdih>
pid_t fork(void);
The new process created by fork is called the child process. This function
The function vfork has the same calling sequence and same return values
as fork. But the semantics of the two functions differ.
The vfork function is intended to create a new process when the purpose
of the new process is to exec a new program.
The vfork function creates the new process, just like fork, without copying
the address space of the parent into the child, as the child won’t reference
that address space; the child simply calls exec (or exit) right after the vfork.
Instead, while the child is running and until it calls either exec or exit, the
child runs in the address space of the parent.
Another difference between the two functions is that vfork guarantees that
the child runs first, until the child calls exec or exit. When the child calls
either of these functions, the parent resumes.
The prototype of vfork is
pid_t vfork(void);
(c) Defin race condition and polling? How to overcome these conditions.
Ans: A race condition occurs when multiple processes are competing for the
same system resource(s). The outcome depends on the order in which the
processes run.
Polling is the continuous (or frequent) checking by a controlling device or
process of other devices, processes, queues, etc. in some defined sequence to
see what state they are in and whether they need attention (such as whether they
are still connected, want to communicate, contain tasks to be executed, etc.).
If a process wants to wait for its parent to terminate, a loop of the following
form could be used:
while (getppid() != 1)
sleep(1);
This type of loop is called polling
To avoid race conditions and to avoid polling, some form of signaling is required
between multiple processes. Signals can be used, and various forms of
interprocess communication (IPC) can also be used.
It is required that each process tells the other when it has finished its initial
set of operations, and that each waits for the other to complete, before
heading off on its own.