OS Lab Manual

48
Title of Assignment: Shell programming and AWK programming with suitable application (student database) and use of advanced filters and report generation. Relevant Theory / Literature Survey: (Brief Theory Expected) About Shell: The shell is a command interpreter that provides a line-oriented interactive and noninteractive interface between the user and the operating system. You enter commands on a command line; they are interpreted by the shell and then sent as instructions to the operating system. The Shell makes available three files. 1)Standard input 2)Standard Output 3)Standard Error 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

Transcript of OS Lab Manual

Page 1: OS Lab Manual

Title of Assignment:

Shell programming and AWK programming with suitable application (student database)

and use of advanced filters and report generation.

Relevant Theory / Literature Survey: (Brief Theory Expected)

About Shell: The shell is a command interpreter that provides a line-oriented interactive and noninteractive interface between the user and the operating system. You entercommands on a command line; they are interpreted by the shell and then sent asinstructions to the operating system.

The Shell makes available three files. 1)Standard input 2)Standard Output 3)Standard Error 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.

Page 2: OS Lab Manual

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.

Steps required to write shell script: 1. Use any editor like vi or mcedit to write shell script.

2. After writing shell script set execute permission for user written script by using chmod command.Ex: chmod permission script-name

Comments : Comments in shell programming start with # and go until the end of the line.  Variables in Shell : In shell programming all variables have the data type string and no need to declare them. There are two types of variable.

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.

Command syntax Purpose

Page 3: OS Lab Manual

echo "some text" write some text on your screenLs list fileswc -l filewc -w filewc -c file

count lines in file orcount words in file orcount number of characters

cp sourcefile destfile copy sourcefile to destfile

grep 'pattern' filesearch for strings in a fileExample: grep 'searchstring' file.txt

Awk

Most of the time awk is used to extract fields from a text line. The default field separator is space. To specify a different one use the option -F. cat file.txt | awk -F, '{print $1 "," $3 }'

2) Pipes and redirection Pipes (|): send the output of one program to the input of another program. Ex.: grep "hello" file.txt | wc -lIt is used to find the lines with the string hello in file.txt and then counts the lines. The output of the grep command is used as input for the wc command.

Redirection: writes the output of a command to a file or appends data to a file > writes output to a file and overwrites the old file in case it exists >> appends data to a file or creates a new one if it doesn't exist already but it never overwrites anything.

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

Page 4: OS Lab Manual

"continue" the loop continues with the next iteration and skips the rest of the loop body. while ...; do .... doneThe 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.

STRUCTURE OF AN AWK PROGRAM :

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.

awk Control Flow Statements :

if ( expr) statement [ else statement]if ( subscript in array) statement [ else statement]

while ( expr) statementfor ( expr ; expr ; expr ) statementfor ( var in array ) statementdo statement while ( expr)

Page 5: OS Lab Manual

# Shell Program for Listing Files in Current Dir# Whose size >= 4096 Bytesecho "SIZE FILE NAME"SizeLimit=4count=0 for f in * # for all files in current Directory do if test -f $f # Check file Types and compare values then fsize=`ls -s $f |awk '{print $1} '` if test $fsize -ge $SizeLimit then csize=`expr $fsize \* 1024` echo $csize - $f count=$[count+1] fi fi doneecho "Total Number of Files:: $count"

root@localhost Unix_Pro]# ./file_size.shSIZE FILE NAME4096 - abc.awk16384 - a.out4096 - child_process.c4096 - db.awk4096 - db.txt4096 - File_Manage.c4096 - file_size.sh4096 - fork1.c16384 - install.log4096 - out.txt4096 - temp.txt4096 - thread_a.c4096 - t_join.c4096 - z.txtTotal Number of Files:: 14

Conclusion:

Studied the various shell programming and AWK commands and their use for generation

of required output.

Page 6: OS Lab Manual

Title of Assignment:

Using fork system call, create child process, suspend it using wait system call and transfer it into zombie state.

Relevant Theory / Literature Survey: (Brief Theory Expected)

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.

Data Structures for Process :

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.

Process States and Transitions :

Page 7: OS Lab Manual

Fork() : This system call is used to create processes. It takes no arguments and returns a process ID. The purpose of fork() is to create a new process, which becomes the child process of the caller. After a new child process is created, both processes will execute the next instruction following the fork() system call. Every process has an entry in the The identification of the parent from the child can be done by testing the returned value of fork().

If fork() returns a negative value, the creation of a child process is unsuccessful. fork() returns a zero to the newly created child process.

fork() returns a positive value, the process ID of the child process, to the parent. The process ID is an integer. A process can use function getpid() to retrieve the process ID assigned to this process.

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(),

Page 8: OS Lab Manual

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.

The execution of wait() could have two possible situations.

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.

Page 9: OS Lab Manual

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.

Page 10: OS Lab Manual

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);}

Page 11: OS Lab Manual

ER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMANDroot 1 0.3 0.0 1372 476 ? S 03:32 0:05 initroot 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 0root 4133 0.0 0.0 1372 432 ? S 03:33 0:00 klogd -xroot 4267 0.0 0.2 3508 1504 ? S 03:33 0:00 /usr/sbin/sshdroot 4281 0.0 0.1 2024 864 ? S 03:33 0:00 xinetd -stayalive -reuse -pidfile /var/run/xinetd.pidroot 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/mouseroot 4329 0.0 0.1 1416 568 ? S 03:33 0:00 crondroot 4340 0.0 0.3 7496 1916 ? S 03:33 0:00 cupsdroot 4408 0.0 0.1 1396 608 ? SN 03:33 0:00 anacron -sroot 4425 0.0 0.0 1348 396 tty1 S 03:33 0:00 /sbin/mingetty tty1root 4426 0.0 0.0 1348 396 tty2 S 03:33 0:00 /sbin/mingetty tty2root 4427 0.0 0.0 1348 396 tty3 S 03:33 0:00 /sbin/mingetty tty3root 4428 0.0 0.0 1348 396 tty4 S 03:33 0:00 /sbin/mingetty tty4root 4429 0.0 0.0 1348 396 tty5 S 03:33 0:00 /sbin/mingetty tty5

Page 12: OS Lab Manual

root 4430 0.0 0.0 1348 396 tty6 S 03:33 0:00 /sbin/mingetty tty6root 4587 0.0 0.2 4356 1440 pts/0 S 03:34 0:00 bashroot 4613 0.0 0.5 8048 2816 pts/0 S 03:34 0:00 vim File_Manage.croot 4616 0.0 0.2 4360 1444 pts/1 S 03:34 0:00 bashroot 4731 0.0 0.2 4368 1460 pts/2 S 03:56 0:00 bashroot 4757 0.0 0.5 8024 2816 pts/2 S 03:57 0:00 vim child_process.croot 4767 0.0 0.2 4364 1444 pts/3 S 03:57 0:00 bashroot 4807 0.0 0.0 1340 236 pts/1 S 04:01 0:00 ./a.outroot 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

Page 13: OS Lab Manual

Title of Assignment:

File management using low level file access system calls such as write, read, open, lseek and fstat.

Relevant Theory / Literature Survey: (Brief Theory Expected)

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

Page 14: OS Lab Manual

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

(a) open system call :

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

Page 15: OS Lab Manual

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.

Syntax : int open (char * pathname, int openFlags);

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:

0 – open for reading

1 – open for writing

2 – open for reading and writing

If an error occurs in trying to open the file, a negative integer is returned.

(b) creat system call :

The named file is created as an empty file and opened for writing and a positive integer, the open

file identifier is returned. The file location is set to 0. The file mode defines file access rights. If

an error occurs in trying to create the file, a negative integer is returned. The open file identifiers

returned by open and creat are local to the process making the calls. Thus, an open file identifier

in one process is not related to an open file identifier in another process.

Syntax : int creat (char * pathname, int fileMode);

(c) close system call:

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);

(d) read system call :

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

Page 16: OS Lab Manual

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.

Syntax: int read (int openFileID, char * bufferAddress, int count);

(e) write system call :

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.

Syntax : int write (int openFileID, char * bufferAddress, int count);

(f) lseek system call :

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.

Syntax : int lseek (int openFileID, inf offset, int moveMode);

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:

0 – use 0 as a base (move from the beginning of the file)

1 – use the current file location as a base (for relative move)

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.

Page 17: OS Lab Manual

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:

Studied various file system commands and their uses.

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#include<sys/stat.h>

Page 18: OS Lab Manual

#include<unistd.h>#include<sys/types.h>void display(int fd){ //function for Displaying FILE int count,buff[2048]; printf("\n\n-------- The Content of FILE is -----------------\n\n"); while((count=read(fd,buff,sizeof(buff)))>0) printf("%s",buff);}

int file_open(char source[40],int mode){ // Function for Opening File int fd; switch(mode){ case 0:fd=open(source,O_RDONLY);break; case 1:fd=open(source,O_WRONLY);break; case 2:fd=open(source,O_RDWR);break; } if(fd==-1) printf("\n\n\t\t*** Cannot OPEN the File...\n"); else printf("\n\n\t\t* * * The File is OPENED Successfully * * *\n\n");

return fd; }

void file_read(char source[40]){ // Function for Reading File int fd,count; fd=file_open(source,0); if(fd!=-1){ display(fd); close(fd); } }

void file_write(char source[40]){ int fd,count; char data[20]; fd=file_open(source,2); if(fd!=-1){ display(fd); printf("\n\n\nEnter the Data to write to File\n\n "); scanf("%s",&data); count=strlen(data); write(fd,data,count); lseek(fd,0L,0); //To read from Begining of File display(fd); close(fd); }}

void file_copy(char source[40]){ // Finction for Copying File int count; int fdold,fdnew; char dest[40],buffer[2048]; printf("\nEnter Name of Destination File:: ");scanf("%s",&dest);

Page 19: OS Lab Manual

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); }}

void file_status(char source[40]){ // Function for File Status int fd; struct stat *buf; char id[20]; fd=file_open(source,0); if(fd!=-1){ stat(source,buf); printf("\n\n\t***The Status of File is***"); printf("\nInode = %d",buf->st_ino); /* inode */ printf("\nProtection Mode = %d",buf->st_mode); /* protection */ printf("\nHard Links = %d",buf->st_nlink); /* number of hard links */ printf("\nUser ID of Owner = %d",buf->st_uid); /* user ID of owner */ printf("\nGroup ID of Owner = %d",buf->st_gid); /* group ID of owner */ printf("\nDevice Type = %d",buf->st_rdev); /* device type (if inode device) */ printf("\nSize(Bytes) = %d",buf->st_size); /* total size, in bytes */ printf("\nBlock Size = %d",buf->st_blksize); /* blocksize for filesystem I/O */ printf("\nBlocks Allocated = %d",buf->st_blocks); /* number of blocks allocated */ //printf("\nLast Access = %d",buf->st_atime); /* time of last access */ //printf("\nLast Modification = %d",buf->st_mtime); /* time of last modification */ //printf("\nLast Change = %d",buf->st_ctime); /* time of last change */ }}

void file_delete(char source[40]){ // Function for DELETING File int val; val=unlink(source); if(val==0) printf("\n\n\t***The File is Deleted SuccessFully***"); else printf("\n\n\tERROR Occured while deleting File....");}void file_seek(char source[40]){ int fd; char c,d;

Page 20: OS Lab Manual

fd=file_open(source,2); if(fd!=-1){ read(fd,&c,1); printf("\n\n\tThe FIRST character in the FILE is :: %c",c); lseek(fd,-2L,2); read(fd,&d,1); printf("\n\n\tThe LAST character in the FILE is :: %c",d); close(fd); }}main(){ int ch; char s[40]; printf("\n\n\tEnter the Name of Source File:: ");scanf("%s",&s);do{ printf("\n\t\tFile Management Operations"); printf("\n\t\t 1.Open File"); printf("\n\t\t 2.Read File"); printf("\n\t\t 3.Write to File"); printf("\n\t\t 4.fstat"); printf("\n\t\t 5.Copy File"); printf("\n\t\t\t 6.Seek File"); printf("\n\t\t\t 7.Delete File"); printf("\n\t\t 8.Exit"); printf("\n\t Your Choice ::"); scanf("%d",&ch); 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);}

[root@localhost Unix_Pro]# gcc File_Manage.c[root@localhost Unix_Pro]# ./a.out

Enter the Name of Source File:: /root/Unix_Pro/temp.txt

Page 21: OS Lab Manual

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 ::1

* * * The File is OPENED Successfully * * *

Enter the Name of Source File:: /root/Unix_Pro/temp_file.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 ::2

* * * The File is OPENED Successfully * * *

-------- The Content of FILE is -----------------

Hi how are You

i am Fine Yarwhat are you doing dud?

Nothing yar, just doing timepass with mobile games.

You have any paln fo the evining?No.then can you come with me to see a film 'Chak De'?yes, why not.I wil br veyr happy with that .

Thank You.

MurlidharRamdasRakshe

Enter the Name of Source File:: /root/Unix_Pro/temp_file.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

Page 22: OS Lab Manual

8.Exit Your Choice ::5

Enter Name of Destination File:: /root/Unix_Pro/tempy.txt

* * * The File is OPENED Successfully * * *----The FILE is Copied Successfully------ * * * The File is OPENED Successfully * * *-------- The Content of FILE is -----------------

Hi how are You

i am Fine Yarwhat are you doing dud?

Nothing yar, just doing timepass with mobile games.

You have any paln fo the evining?No.then can you come with me to see a film 'Chak De'?yes, why not.I wil br veyr happy with that .

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:

Page 23: OS Lab Manual

Simultaneous execution of two or more threads.

Relevant Theory / Literature Survey: (Brief Theory Expected)

Threads:

A thread is a single sequence stream within a process. Threads are executed within a process.

They are sometimes called lightweight processes. In a process, threads allow multiple

executions of streams. Threads are popular way to improve application through parallelism.

The CPU switches rapidly back and forth among the threads giving illusion that the threads are

running in parallel. Like a traditional process i.e., process with one thread, a thread can be in

any of several states (Running, Blocked, Ready or Terminated). Each thread has its own stack.

A thread consists of a program counter (PC), a register set, and a stack space. Threads are not

independent of one other like processes as a result threads shares with other threads their

code section, data section, OS resources also known as task, such as open files and signals.

Processes Vs Threads:

Similarities

Threads share CPU and only one thread active (running) at a time.

Threads within a process, execute sequentially.

Thread can create children.

If one thread is blocked, another thread can run.

Differences:

Threads are not independent of one another.

All threads can access every address in the task belonging to same process.

Page 24: OS Lab Manual

Advantages of threads:

o As threads can share common data, they do not need to

use IPC.

o They only need a stack and storage for registers for creation of threads.

o Threads do not need new address space, global data, program code.

o Contexts switching is fast when working with threads.

Disadvantage: There is no protection between threads.

Types of threads :

(1) User-Level Threads : User-level threads implement in user-level

libraries, rather than via systems calls, so thread switching does not

need to call operating system and to cause interrupt to the kernel. In

fact, the kernel knows nothing about user-level threads and manages

them as if they were single-threaded processes.

The user can accomplish this by moving the stack point at his discretion. This reduces the overhead for the initial programming by the writer of the operating system. Also, user-level threads usually switch faster than kernel-level threads which adds to processor efficiency.

There are three main disadvantages to user-level 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.

Page 25: OS Lab Manual

(2) Kernel-Level Threads: Since the only advantage in Linux of using user-level

threads is cooperative multitasking, Linux primarily uses kernel-level threads. In this

method, the kernel knows about and manages the threads. The kernel

has a thread table that keeps track of all threads in the system. In

addition, the kernel also maintains the traditional process table to

keep track of processes. Operating Systems kernel provides system

call to create and manage threads.

There are many advantages of using this method. Input/output blocking is not a problem as it is in user-level. Also, the operating system’s code can take advantage of symmetric multiprocessing.

How the Kernel Accesses the Threads

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.

Advantages of Threads over Multiple Processes

Context Switching Threads are very inexpensive to create and destroy, and they are

inexpensive to represent. For example, they require space to store, the PC, the SP, and the

general-purpose registers, but they do not require space to share memory information,

Information about open files of I/O devices in use, etc. With so little context, it is much faster to

switch between threads.

Sharing Threads allow the sharing of a lot resources that cannot be shared in process,

for example sharing code section, data section, Operating System resources like open file etc.

Page 26: OS Lab Manual

Disadvantages of Threads over Multi processes

Blocking The major disadvantage if that if the kernel is single threaded, a system call of

one thread will block the whole process and CPU may be idle during the blocking period.

Security Since there is, an extensive sharing among threads there is a potential problem

of security. It is quite possible that one thread over writes the stack of another thread although

it is very unlikely since threads are meant to cooperate on a single task.

Basic thread primitives: There are various primitives that a thread system must provide.

thread_create : It is used to create a new thread.

Syntax :

Int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(* start_routine) (void *),

void *arg)

Pthread_t : It is defining a thread pointer. When a thread is created identifier is written into the

variable to which the pointer points. This identifier helps to refer to thread.

Pthread_attr_t : It is used to set the thread attributes. Usually there is no need to set the thread

attributes. Pass this argument as NULL.

Name of function : The name of the function to be started by the thread for execution.

Arguments to be passed to the function : When a new thread is created it executes the

function pointed by the function variable name.

pthread_join : It is used to wait for the thread represented in the thread_join call.It waits for

the thread represented in the call to finish executing. It is analogous to wait() in Unix. It waits

for the specified thread to complete, and gathers information about the thread's exit status.

Syntax : Int pthread_join(pthread_t th , void *threadreturn);

Page 27: OS Lab Manual

First argument is the thread for which to wait.Second argument is pointer to pointer that points

to return value from the thread.

Pthread_exit: This function is used to terminate the calling thread.

Syntax : Void pthread_Exit(void *retval);

/*Program : Multithreading*/#include<stdio.h>#include<pthread.h>#include<unistd.h>#include<stdlib.h>

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);

Page 28: OS Lab Manual

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]); } }

}

void display(int X[5][5],int a,int b){ int i,j; printf("\n\t\t\t"); for(i=0;i<a;i++){ for(j=0;j<b;j++){ printf(" %d",X[i][j]); } printf("\n\t\t\t"); }}

void *Add(void *arg){ int i,j; for(i=0;i<m;i++){ for(j=0;j<n;j++){ C[i][j]=A[i][j]+B[i][j]; printf("\n\tIn ADDITION Function"); sleep(1); }

Page 29: OS Lab Manual

} printf("\n\n\t\t\tThe Addition is Over"); display(C,m,n); pthread_exit(NULL);}void *Sub(void *arg){ int i,j; for(i=0;i<m;i++){ for(j=0;j<n;j++){ D[i][j]=A[i][j]-B[i][j]; printf("\n\t\tIn SUBSTRACTION Function"); sleep(1); } } printf("\n\n\t\t\tThe Substraction is Over"); display(D,m,n); pthread_exit(NULL);}

void *Mul(void *arg){ int i,j,k; for(i=0;i<m;i++){ for(j=0;j<q;j++){ E[i][j]=0; for(k=0;k<n;k++){ E[i][j]+=A[i][k]*B[k][j]; printf("\n\t\t\tIn MULTIPLICATION Function"); sleep(1); } } } printf("\n\n\t\t\tThe Multiplaication is Over"); display(E,m,q); pthread_exit(NULL);}

-------------------OUTPUT--------------------

[root@localhost Thread]# gcc mat.c -lpthread[root@localhost Thread]# ./a.out Enter The Order of Matrix A(m*n) :: 2 2 Enter The Elements A[0][0]==1 A[0][1]==2 A[1][0]==1 A[1][1]==3 Enter The Order of Matrix B(p*q) :: 2 2 Enter The Elements B[0][0]==1

Page 30: OS Lab Manual

B[0][1]==3 B[1][0]==2 B[1][1]==1

The Entered Matrices are 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 The Addition is Over 2 5 3 4 The Substraction is Over 0 -1 -1 2 In MULTIPLICATION Function In MULTIPLICATION Function In MULTIPLICATION Function In MULTIPLICATION Function The Multiplaication is Over 5 5 7 6

[root@localhost Thread]# ./a.out Enter The Order of Matrix A(m*n) :: 2 3 Enter The Elements A[0][0]==1 A[0][1]==2 A[0][2]==1 A[1][0]==2 A[1][1]==3 A[1][2]==1

Page 31: OS Lab Manual

Enter The Order of Matrix B(p*q) :: 3 2 Enter The Elements B[0][0]==1 B[0][1]==1 B[1][0]==1 B[1][1]==1 B[2][0]==1 B[2][1]==1 The Entered Matrices are 1 2 1 2 3 1

1 1 1 1 1 1 For Addition and Substraction the order of Matrices Should be Same 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 The Multiplaication is Over 4 4 6 6

Conclusion:

Studied difference between threads and processes, advantages and disadvantages,

creation of threads and uses of threads.

Page 32: OS Lab Manual

Title of Assignment:

Write and insert linux kernel module.

Relevant Theory / Literature Survey: (Brief Theory Expected)

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

Page 33: OS Lab Manual

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.

Page 34: OS Lab Manual

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>

Page 35: OS Lab Manual

#include <linux/init.h>

static int a,b;MODULE_PARM(a,"i");MODULE_PARM(b,"b");

static int s_module(void){ int c=0;

printk("<1>hello world\n"); c=2+3; printk("sum is %d\n",c); return 0;}

static void e_module(void){ printk("<1>good bye \n");}

module_init(s_module);module_exit(e_module);

MODULE_LICENSE("GPL");

[root@localhost root]# vi raj.c

[root@localhost root]# make file

gcc -DMODULE -D__KERNEL__ -isystem /lib/modules/`uname -r`/build/include file.c -o file

file.c: In function `read1':

file.c:62: void value not ignored as it ought to be

file.c: In function `write1':

[root@localhost root]# make

gcc -DMODULE -D__KERNEL__ -isystem /lib/modules/`uname -r`/build/include -c -o abhi.o abhi.c

Page 36: OS Lab Manual

[root@localhost root]# insmod -f raj.ko

Warning: kernel-module version mismatch

raj.ko was compiled for kernel version 2.4.20

while this kernel is version 2.4.20-8

Warning: loading raj.ko will taint the kernel: forced load

See http://www.tux.org/lkml/#export-tainted for information about tainted modules

Module raj.ko loaded, with warnings

[root@localhost root]# lsmod

Module Size Used by Tainted: GF

raj.ko 856 0 (unused)

ide-cd 35708 0 (autoclean)

cdrom 33728 0 (autoclean) [ide-cd]

soundcore 6404 0 (autoclean)

parport_pc 19076 1 (autoclean)

lp 8996 0 (autoclean)

parport 37056 1 (autoclean) [parport_pc lp]

autofs 13268 0 (autoclean) (unused)

ipt_REJECT 3928 6 (autoclean)

iptable_filter 2412 1 (autoclean)

ip_tables 15096 2 [ipt_REJECT iptable_filter]

keybdev 2944 0 (unused)

mousedev 5492 1

hid 22148 0 (unused)

input 5856 0 [keybdev mousedev hid]

usb-uhci 26348 0 (unused)

Page 37: OS Lab Manual

ehci-hcd 19976 0 (unused)

usbcore 78784 1 [hid usb-uhci ehci-hcd]

ext3 70784 2

jbd 51892 2 [ext3]

[root@localhost root]# mkdir -p/lib/modules/$(uname -r)/kernel/drivers/raj

[root@localhost root]#cp raj.c raj.ko

[root@localhost root]# vi /etc/modules

[root@localhost root]# reboot

[root@localhost root]# insmod -f raj.ko

[root@localhost root]# dmesg

dmesg

Linux version 2.4.20-8 ([email protected]) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #1 Thu Mar 13 17:54:28 EST 2003

BIOS-provided physical RAM map:

hello world

[root@localhost root]# rmmod raj.ko

[root@localhost root]# dmesg

Linux version 2.4.20-8 ([email protected]) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #1 Thu Mar 13 17:54:28 EST 2003

BIOS-provided physical RAM map:

hello world

sum is 5

good bye

Page 38: OS Lab Manual

Conclusion:

Studied the different commands used in loading and unloading of kernel module.