OS Lab Manual
OS Lab Manual
OS Lab Manual
Shell programming and AWK programming with suitable application (student database)
and use of advanced filters and report generation.
It can manipulate the default source and destination of input and output streams by
assigning them to disk files.
How it Works:
(1)Parsing : The shell first breaks up the command line into words using spaces and
tabs as delimiters, unless quoted. All consecutive occurrence of a space or tabs is
replaced with single space.
(2)Variable Evaluation : All $-prefixed strings are evaluated as variables, unless
quoted or escaped.
(3)Command Substitution : Any command surrounded by back quotes is executed by
the shell, which then replaces standard output of the command into command line.
(4)Redirection : The shell then looks for the characters >, < and >> to open the files
they point to.
(5)Wild-card interpretation : The shell finally scans the command line for wild-cards
(*, ?, [ and ] ). Any word containing a wild-card is replaced by a sorted list of file
names that match the pattern. The list of these filenames then forms arguments to
the command.
(6)PATH evaluation : It finally looks for the PATH variable to determine the
sequence of directories it has to search in order to hunt for the command.
Linux Shell : Shell accepts user instruction or commands and if its a valid command it is
passed to kernel. Shell provides an environment for user interaction. Shell is a command
language interpreter that executes commands read from the standard input device or from
a file. Shell is not part of system kernel but uses the system kernel to execute programs.
Several shells available with Linux are as below.
BASH ( Bourne-Again SHell ) : Most commonly used shell in Linux. It is Freeware
shell. It was developed by Brian Fox and Chet Ramey at Free Software Foundation.
CSH (CShell) : The C shell's syntax and usage are very similar to the C programming
language. It was developed by Bill Joy at University of California (For BSD).
KSH (Korn Shell) : It was developed by David Korn AT & T Bell Labs.
TCSH : TCSH is an enhanced but completely compatible version of the Berkeley UNIX
C shell.
To find all available shells in the system use the following command
$ cat /etc/shells
To find the current shell use the following command
$ echo $SHELL
Shell Script : Shell Script is series of command written in plain text file. Shell script is
just like batch file is MS-DOS.
1. System variables : Created and maintained by Linux itself. These variables are
defined in capital letters.
2. User defined variables (UDV) : Created and maintained by user. This type of variable
is defined in lower letters.
In shell program there are also environment variables which are preceded by the keyword
export.
Shell commands and control structures:There are three categories of commands which
can be used in shell scripts:
1) Unix commands:
Shell script can make use of any unix commands. Some of the commands which are
more often used than others are as below.
3) Control structures
"if" statement : It tests the condition and if the condition is true "then" part gets
executed otherwise else part is executed.
if ....; then
....
elif ....; then
....
else
....
fi
case statement : It can be used to match a given string against a number of possibilities.
case ... in
...) do something here;;
esac
Loop statements :The while-loop will run while the expression given if it is true. The
keyword "break" can be used to leave the loop at any point in time. With the keyword
"continue" the loop continues with the next iteration and skips the rest of the loop body.
while ...; do
....
done
The for-loop takes a list of strings (strings separated by space) and assigns them to a
variable.
for var in ....; do
....
done
AWK: awk is a programming language designed to search for, match patterns, and
perform actions on files.Programs in awk are different from programs in most other
languages, because awk programs are data-driven.
awk scans input lines one after the other, searching each line to see if it matches a set of
patterns or conditions specified in the awk program. For each pattern, an action is
specified. The action is performed when the pattern matches that of the input line. Thus,
an awk program consists of a number of patterns and associated actions. Actions are
enclosed using curly braces and separated using semi-colons.
pattern { action }
pattern { action }
When awk scans an input line, it breaks it down into a number of fields. Fields are
separated by a space or tab character. Fields are numbered beginning at one, and the
dollar symbol ($) is used to represent a field. Field zero ($0) refers to the entire line. awk
scans lines from a file(s) or standard input.
printf: Built in function of awk called printf operates the same way as in the C
programming language. It is terminated by a semi-colon. Brackets are used to enclose the
argument, and the text is enclosed using double quotes.
Conclusion:
Studied the various shell programming and AWK commands and their use for generation
of required output.
Title of Assignment:
Using fork system call, create child process, suspend it using wait system call
and transfer it into zombie state.
Process: Process is an active entity that executes a given piece of code. It has its own
execution stack, own set of memory pages, own file descriptors table and a unique
process ID. Several processes may be executing the same or different program at the
same time for the same user or for several different users.
Every process has an entry in the kernel process table, and each process alocated a user
area that contains private data manipulated only by the kernel. The process table contains
(or points to) per process region table, whose entries point to entries in the region table.A
region table is a contiguous area of process address's space, such as text, data and stack.
Unix will make an exact copy of the parent’s address space and give it to the child. So the
parent and child processes have separate address spaces. Since both processes have
identical but separate address spaces, those variables initialized before fork() call have
the same values in both address spaces. Since every process has its own address space,
any modifications will be independent of the others. In other words, if the parent changes
the value of its variable, the modification will only affect the variable in the parent
process's address space. Other address spaces created by fork() calls will not be affected
even though they have identical variable names. When the main program executes fork(),
an identical copy of its address space, including the program and all data, is created.
System call fork() returns the child process ID to the parent and returns 0 to the child
process.
Zombie state of process : Once a child process is created , there are two possibilities.
Either the parent process exits before the child, or the child exits before the parent.
When a child process exits, it is not immediately cleared off from the process table.
Instead, a signal is sent to its parent process, which needs to acknowledge it's
child's death, and only then the child process is completely removed from the
system. In the duration before the parent's acknowledgment and after the child's
exit, the child process is in a state called "zombie". When the parent process is not
properly coded, the child remains in the zombie state forever. Such processes can
be noticed by running the 'ps' command (shows the process list) and seeing
processes having string "<defunct>" as their command name.
wait() :This system call blocks the calling process until one of its child processes exits or
a signal is received. wait() takes the address of an integer variable and returns the
process ID of the completed process. Some flags that indicate the completion status
of the child process are passed back with the integer pointer. One of the main
purposes of wait() is to wait for completion of child processes.
The simple way of a process to acknowledge the death of a child process is by using the
wait() system call. When wait() is called, the process is suspended until one of its child
processes exits, and then the call return with the exit status of the child process. If it has a
zombie child process, the call returns immediately, with the exit status of that process.
1. If there are at least one child processes running when the call to wait() is made,
the caller will be blocked until one of its child processes exits. At that moment,
the caller resumes its execution.
2. If there is no child process running when the call to wait() is made, then this
wait() has no effect at all. That is, it is as if no wait() is there.
exit() : This system call is used to terminate the current process.The exit code or return
code is a numeric value returned by a terminating process to its parent process.
Conclusion:
Studied the creation of a child process, identification of child and parent process,
suspension of a process and transferring the process to zombie state.
Addition of six numbers………………………………
#include<unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
int main()
{
int x[6] = {1,2,3,4,5,6};
int a,b,c;
static int i = 0 ;
pid_t pid;
pid = fork();
if(pid == 0) {
a = x[i] + x[i+1];
i += 2;
pid = fork();
if(pid == 0){
b = x[i] + x[i+1];
i += 2;
pid = fork();
if(pid == 0) {
c = x[i] + x[i+1];
i += 2;
pid = fork();
if(pid == 0) {
a = a + b;
pid = fork();
if(pid == 0){
c = a + c;
printf("\nSUM = %d\n",c);
}
}
}
}
}
if(pid != 0) {
int stat_val;
pid_t child_pid;
child_pid = wait(&stat_val);
}
exit(0);
}
ER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.3 0.0 1372 476 ? S 03:32 0:05 init
root 2 0.0 0.0 0 0 ? SW 03:32 0:00
[migration/0]
root 3 0.0 0.0 0 0 ? SW 03:32 0:00
[migration/1]
root 4 0.0 0.0 0 0 ? SW 03:33 0:00 [keventd]
root 5 0.0 0.0 0 0 ? SWN 03:33 0:00
[ksoftirqd_CPU0]
root 6 0.0 0.0 0 0 ? SWN 03:33 0:00
[ksoftirqd_CPU1]
root 11 0.0 0.0 0 0 ? SW 03:33 0:00 [bdflush]
root 7 0.0 0.0 0 0 ? SW 03:33 0:00 [kswapd]
root 8 0.0 0.0 0 0 ? SW 03:33 0:00
[kscand/DMA]
root 9 0.0 0.0 0 0 ? SW 03:33 0:00
[kscand/Normal]
root 10 0.0 0.0 0 0 ? SW 03:33 0:00
[kscand/HighMem]
root 12 0.0 0.0 0 0 ? SW 03:33 0:00
[kupdated]
root 13 0.0 0.0 0 0 ? SW 03:33 0:00
[mdrecoveryd]
root 17 0.1 0.0 0 0 ? SW 03:33 0:02
[kjournald]
root 75 0.0 0.0 0 0 ? SW 03:33 0:00 [khubd]
root 3874 0.0 0.0 0 0 ? SW 03:33 0:00
[kjournald]
root 4129 0.0 0.1 1444 548 ? S 03:33 0:00 syslogd
-m 0
root 4133 0.0 0.0 1372 432 ? S 03:33 0:00 klogd -x
root 4267 0.0 0.2 3508 1504 ? S 03:33 0:00
/usr/sbin/sshd
root 4281 0.0 0.1 2024 864 ? S 03:33 0:00 xinetd
-stayalive -reuse -pidfile /var/run/xinetd.pid
root 4301 0.0 0.4 5916 2496 ? S 03:33 0:00
[sendmail]
root 4320 0.0 0.0 1412 444 ? S 03:33 0:00 gpm -t
imps2 -m /dev/mouse
root 4329 0.0 0.1 1416 568 ? S 03:33 0:00 crond
root 4340 0.0 0.3 7496 1916 ? S 03:33 0:00 cupsd
root 4408 0.0 0.1 1396 608 ? SN 03:33 0:00 anacron
-s
root 4425 0.0 0.0 1348 396 tty1 S 03:33 0:00
/sbin/mingetty tty1
root 4426 0.0 0.0 1348 396 tty2 S 03:33 0:00
/sbin/mingetty tty2
root 4427 0.0 0.0 1348 396 tty3 S 03:33 0:00
/sbin/mingetty tty3
root 4428 0.0 0.0 1348 396 tty4 S 03:33 0:00
/sbin/mingetty tty4
root 4429 0.0 0.0 1348 396 tty5 S 03:33 0:00
/sbin/mingetty tty5
root 4430 0.0 0.0 1348 396 tty6 S 03:33 0:00
/sbin/mingetty tty6
root 4587 0.0 0.2 4356 1440 pts/0 S 03:34 0:00 bash
root 4613 0.0 0.5 8048 2816 pts/0 S 03:34 0:00 vim
File_Manage.c
root 4616 0.0 0.2 4360 1444 pts/1 S 03:34 0:00 bash
root 4731 0.0 0.2 4368 1460 pts/2 S 03:56 0:00 bash
root 4757 0.0 0.5 8024 2816 pts/2 S 03:57 0:00 vim
child_process.c
root 4767 0.0 0.2 4364 1444 pts/3 S 03:57 0:00 bash
root 4807 0.0 0.0 1340 236 pts/1 S 04:01 0:00 ./a.out
root 4808 0.0 0.0 0 0 pts/1 Z 04:01 0:00 [a.out
<defunct>]
root 4809 0.0 0.1 2656 708 pts/3 R 04:01 0:00 ps ux
Title of Assignment:
File management using low level file access system calls such as write, read, open, lseek and
fstat.
Unix file system is organized as a tree with single root node called root. Every non-leaf
node is of the file system is a directory of files and files at the leaf nodes of the tree are
either directories, regular files, or special device files. The name of the file is given by a
pathname which describes how to locate the file in the system hierarchy. Each file on
unix system has a unique inode. The inode contains the information necessary for a
process to access a file like file ownership, access rights, file size and location of file’s
data in the file system. Processes access the files by a well defined set of system calls
and specify the file by a character string that is the pathname. Unix provides system calls
for creation of file, deletion of file, reading the content of file, writing the information
into the file etc. Some of the system calls for accessing, creating, reading, writing
operations of file are as below.
An Overview of the File Subsystem :
Data Structures For File subsystem
The internal representation of a file is given by inode, which contains a description
of the disk layout of the file data and other information. Every file has one inode, but it
may have several names (link). When a process refers to a file by name, the kernel parses
the file name one component at a time, checks that process has permissions to search the
directories in the path, and eventually retrieves the inode for the file.
When a process creates a new file, the kernel assign it an unused inode. inodes are
stored in the file system, and reads them into an inode table when manipulating files.
The File System Layout is as shown in the Figure
The open system call creates an operating system object called an open file. The open file is
logically connected to the file as mentioned in the open system call. An open file has a file
location associated with it. It is the offset in the file where the next read or write will start. After
opening a file, read or write system calls are used to read or write the open file. Each read or
write system call increments a file location for a number of characters read or written. Thus, the
file is read (or/and written) sequentially by default.
The named file is opened and a positive integer, the open file identifier is returned. The file
location is set to 0. The flags can be one of the following:
The file is closed by using close system call. A return code 0 means the close succeeded.
A return value -1 means that the openFileID did not refer to open file.
Syntax : int close (int openFileID);
The operating system tries to read count bytes from the open file designated by openFileID. The
bytes are read from the file starting at the offset provided by the file location. If fewer then count
bytes are left before the end of the file all remaining bytes are read. This is not considered to be
an error. The bytes read are places into the array of bytes starting at bufferAddress. The file
location is increased by the number of bytes read. The return value is the number of bytes that
were actually read, and this might be less than count. A return value 0 indicates that the end of
file has been reached and the file location is equal to the size of the file, thus no more bytes can
be read. A negative return value indicates some error occurred in the read.
The operating system tries to write coun bytes to the open file designated by openFileID. The
bytes are written to the file starting at the offset provided by the file location. The bytes are taken
from the array of bytes starting at bufferAddress. The file location is increased by the number of
bytes read. The return value is the number of bytes that were actually written. A negative return
value indicates some error occurred in the write. For causes of different negative values see man
pages. Note that the write system call specifies into which file to write, and from where to take
and how many characters for writing, but it does not indicate where in the file to write. The
location into file is not passed with the call but it is kept with open file information as a part of
the file state.
It is used to achieve random access into the file since it changes the file location that will be used
for the next read or write. Close the open file using the close system call after completing the
work with the open file.
The file location associated with the open file is changed to a new value. The new value is
computed by adding the offset to the base. The base is selected according to the moveMode as
follows:
2 – use the current file size as a base (move from the end of the file). Positive values of the offset
will cause the next write to be beyond the current end of the file. A 0 value will cause the next
write to extend the file.
The returned value is the new file position. An lseek with an offset of 0 and a moveMode
of 1 will not change the file position but will return the current file position. If an error
occurs, a negative integer is returned.
(i) unlink system call :
It is used to delete the file. A return code 0 means the unlink succeeded. If an error occurs
in trying to delete a file, a negative integer is returned.
Syntax : int unlink (char * pathname);
Conclusion:
return fd;
}
fdold=file_open(source,0);
fdnew=creat(dest,0666);
if(fdnew==-1) printf("\nCannot Creat the File...");
if((fdold!=-1)&&(fdnew!=-1)){
while((count=read(fdold,buffer,sizeof(buffer)))>0){
write(fdnew,buffer,count);
}
printf("\n\n----The FILE is Copied Successfully------");
file_read(dest);
close(fdold);
close(fdnew);
}
}
switch(ch){
case 1:file_open(s,0);break;
case 2:file_read(s);break;
case 3:file_write(s);break;
case 4:file_status(s);break;
case 5:file_copy(s);break;
case 6:file_seek(s);break;
case 7:file_delete(s);break;
case 8:break;
default:printf("\n\n\tWRONG Choice...");
}
}while(ch!=8);
exit(0);
}
i am Fine Yar
what are you doing dud?
Thank You.
MurlidharRamdasRakshe
i am Fine Yar
what are you doing dud?
Thank You.
MurlidharRamdasRakshe
Enter the Name of Source File:: /root/Unix_Pro/tempy.txt
File Management Operations
1.Open File
2.Read File
3.Write to File
4.fstat
5.Copy File
6.Delete File
7.Seek File
8.Exit
Your Choice ::6
***The File is Deleted SuccessFully***
Title of Assignment:
Threads:
• Threads share CPU and only one thread active (running) at a time.
Differences:
• All threads can access every address in the task belonging to same
process.
Advantages of threads:
One, starvation can often occur if one thread takes up too much of the time-slice.
The second is if one thread gets blocked, all other threads in that process will lose
their timeslice.
Finally, it cannot take advantage of any operating systems that can use symmetric
multiprocessing.
(2) Kernel-Level Threads: Since the only advantage in Linux of using user-level
Each process contains at least one parent thread and as each thread is spawned, it is
assigned a TID, thread identification. Each thread also contains a PID, parent
identification. All threads that are children of the same parent are assigned the same
PID. Each thread can be referred to individually or as a group. For example, an
application has three threads, one parent and two children, and the threads share
the parent's PID. If the TID for the parent is 0x00011234 and the children’s TID’s are
0x00021234 and 0x00031234, each thread can be accessed with the address
0x00001234.
Basic thread primitives: There are various primitives that a thread system
must provide.
Syntax :
Name of function : The name of the function to be started by the thread for
execution.
int A[5][5],B[5][5],C[5][5],D[5][5],E[5][5],m,n,p,q;
void *Add(void *);
void *Sub(void *);
void *Mul(void *);
void accept();
void display(int X[5][5],int a,int b);
int main(){
pthread_t t_add,t_sub,t_mul;
void *retval;
int res1,res2,res3,res;
accept();
printf("\n\n\tThe Entered Matrices are \n ");
display(A,m,n);
display(B,p,q);
printf("\n");
if(m==p&&n==q){
pthread_create(&t_add, NULL, Add, (void *) res);
pthread_create(&t_sub, NULL, Sub, (void *) res);
pthread_create(&t_mul, NULL, Mul, (void *) res);
res1=pthread_join(t_add,&retval);
res2=pthread_join(t_sub,&retval);
res3=pthread_join(t_mul,&retval);
}
else{
printf("\n\tFor Addition and Substraction the order of Matrices
Should be Same\n\n ");
if(n==p){
pthread_create(&t_mul, NULL, Mul, (void *) res);
res3=pthread_join(t_mul,&retval);
}
else printf("\n\t\tFor Multiplaication A(n) Should be Equal to
B(p)");
}
exit(EXIT_SUCCESS);
}
void accept(){
int i,j;
printf("\n\n\tEnter The Order of Matrix A(m*n) :: ");scanf("%d
%d",&m,&n);
printf("\n\n\t\tEnter The Elements");
for(i=0;i<m;i++){
for(j=0;j<n;j++){
printf("\n\t\t\tA[%d][%d]==",i,j);scanf("%d",&A[i][j]);
}
}
printf("\n\n\tEnter The Order of Matrix B(p*q) :: ");scanf("%d
%d",&p,&q);
printf("\n\n\t\tEnter The Elements");
for(i=0;i<p;i++){
for(j=0;j<q;j++){
printf("\n\t\t\tB[%d][%d]==",i,j);scanf("%d",&B[i][j]);
}
}
-------------------OUTPUT--------------------
1 2
1 3
1 3
2 1
In ADDITION Function
In SUBSTRACTION Function
In MULTIPLICATION Function
In ADDITION Function
In SUBSTRACTION Function
In MULTIPLICATION Function
In ADDITION Function
In SUBSTRACTION Function
In MULTIPLICATION Function
In ADDITION Function
In SUBSTRACTION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
1 2 1
2 3 1
1 1
1 1
1 1
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
In MULTIPLICATION Function
Conclusion:
Linux operates in two modes--the Kernel mode (kernel space) and the User mode (user
space). The kernel works in the highest level (also called supervisor mode) where it has
all the authority, while the applications work in the lowest level where direct access to
hardware and memory are prohibited. Linux transfers the execution from user space to
the kernel space through system calls and the hardware interrupts. The Kernel code
executing the system call works in the context of the process, which invokes the system
call. As it operates on behalf of the calling process, it can access the data in the processes
address space. The kernel code that handles interrupts, works to the processes and
related to any particular process.
Linux Kernel Module :The Linux kernel is a monolithic kernel i.e. it is one single large
program where all the functional components of the kernel have access to all of its
internal data structures and routines. The alternative to this is the micro kernel structure
where the functional pieces of the kernel are broken out into units with strict
communication mechanism between them. This makes adding new components into the
kernel, via the configuration process, rather time consuming. This is the best alternative
to dynamically load and unload the components of the operating system using Linux
Kernel Modules. The Linux kernel modules are piece of codes, which can be dynamically
linked to the kernel even after the system bootup. They can be unlinked from the kernel
and removed when they are no longer needed. Mostly the Linux kernel modules are used
for device drivers such as network drivers or file system. When a Linux kernel module is
loaded, it becomes a part of the Linux kernel as the normal kernel code and functionality
and it posses the same rights and responsibilities as the kernel code. Every kernel module
needs to include linux/module.h.
Modules are pieces of code that can be loaded and unloaded into the kernel
upon demand. They extend the functionality of the kernel without the need to
reboot the system.
A program usually begins with a main() function, executes a bunch of instructions and
terminates upon completion of those instructions. Kernel modules work a bit differently.
Module always begin with either the init_module or the function specified with
module_init call. This is the entry function for modules; it tells the kernel what
functionality the module provides and sets up the kernel to run the module's functions
when they're needed. Once it does this, entry function returns and the module does
nothing until the kernel wants to do something with the code that the module provides.
All modules end by calling either cleanup_module or the function you specify with the
module_exit call. This is the exit function for modules; it undoes whatever entry
function did. It unregisters the functionality that the entry function registered.Every
module must have an entry function and an exit function.
Init_module(): The init_module is called when the module is inserted into the kernel The
module is registered to the kernel and attaches its data-structures and functionality to the
kernel. The kernel-defined external functions are also resolved.
cleanup_module(): This module is called just before removing the module from the
kernel. It `unregisters' the module functionality from the kernel.
Loading modules : insmod command loads the `loadable kernel modules' in the running
kernel. insmod tries to link a module into the running kernel by resolving all the symbols
from the kernel's exported `symbol table'. When the Linux kernel discovers the need for a
module, the kernel requests to the kernel daemon to load the appropriate module. The
kernel daemon is the process having exclusive superuser privileges. At the time of
booting, it opens the IPC channel to the kernel and uses it for transferring messages
(request for loading modules), to and from the kernel. While loading the module, the
kerneld calls modprobe and insmod to load the required module. The demand loadable
kernel modules are usually located at /lib/module/ directory.
Insmod : The insmod depends on some critical system calls to load the module to the
kernel. It is used to insert a module into the Linux Kernel.It uses the sys_create_module
to allocate kernel memory to hold module. It uses get_kernel_syms system call to get the
kernel symbol table in order to link the module. It then calls the sys_init_module system
call to copy the relocatable object code of the module to the kernel space. And soon after
this, insmod calls the initialization function of the concerned module i.e. init_module.
These system are in kernel/module.c.
Unloading modules : The modules can be unloaded using rmmod command. While removing
modules, rmmod ensures the restriction that the modules are not in use and they are not referred
by any other module or the part of the kernel. The cleanup_module function of the concerned
module is called to freeup the kernel resources it has allocated. After the successful execution of
the cleanup_module, the module datastructure is marked DELETED and it is unlinked from the
kernel and unlisted from the list of kernel modules. The reference list of the modules on which it
is dependent is modified and dependency is released. The kernel memory allocated to the
concerned module is deallocated and returned to the kernel memory spool.
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
module_init(s_module);
module_exit(e_module);
MODULE_LICENSE("GPL");
lp 8996 0 (autoclean)
mousedev 5492 1
ext3 70784 2
dmesg
hello world
hello world
sum is 5
good bye
Conclusion: