li-booklet (2)
li-booklet (2)
a1 b1 a1 + b1
.. + .. = ..
an bn an + bn
Is it C or Linux?
By Emertxe
Version 2.2 (December 18, 2014)
2 System Calls 13
2.1 User and Kernel spaces . . . . . . . . . . . . . . . . . . . . . . 13
2.2 System Calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.2.1 System Calls and Library functions . . . . . . . . . . . 15
2.2.2 System Calls in Detail . . . . . . . . . . . . . . . . . . 15
2.2.3 Tracing System Calls . . . . . . . . . . . . . . . . . . . 16
2.3 System Call Examples . . . . . . . . . . . . . . . . . . . . . . 16
iii
3 Processes 25
3.1 Processes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.1.1 What is a Process? . . . . . . . . . . . . . . . . . . . . 25
3.1.2 Process Versus Program . . . . . . . . . . . . . . . . . 26
3.2 Process States . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
3.2.1 Process state Transitions . . . . . . . . . . . . . . . . . 27
3.3 Schedular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.3.1 Operations . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.4 Process Descriptor/Structure . . . . . . . . . . . . . . . . . . 28
3.4.1 State Field . . . . . . . . . . . . . . . . . . . . . . . . . 28
3.4.2 Process ID . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.5 Basic Process Management . . . . . . . . . . . . . . . . . . . . 31
3.5.1 Viewing active process (Commands) . . . . . . . . . . 31
3.5.2 Getting Process ID in C-Program . . . . . . . . . . . . 32
3.5.3 Foreground and background process and killing a process 32
3.5.4 Context switch . . . . . . . . . . . . . . . . . . . . . . 33
3.5.5 Process Scheduling Queues . . . . . . . . . . . . . . . . 34
3.6 Creating a Process . . . . . . . . . . . . . . . . . . . . . . . . 35
3.6.1 system() Function . . . . . . . . . . . . . . . . . . . . . 35
3.6.2 fork()-Creating a New Process . . . . . . . . . . . . . . 35
3.6.3 vfork() . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
3.6.4 exec()-Replacing Process Image . . . . . . . . . . . . . 37
3.6.5 exec family . . . . . . . . . . . . . . . . . . . . . . . . 38
3.6.6 Shortcomings of fork() and exec() . . . . . . . . . . . . 38
3.6.7 Copy-On-Write (COW) . . . . . . . . . . . . . . . . . . 39
3.7 Wait Family of System Calls . . . . . . . . . . . . . . . . . . . 39
3.8 Special Case of Processes . . . . . . . . . . . . . . . . . . . . . 40
3.8.1 Zombie Process . . . . . . . . . . . . . . . . . . . . . . 40
3.8.2 Orphan Process . . . . . . . . . . . . . . . . . . . . . . 40
3.9 Practice - I . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.9.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . 41
3.9.2 Objective . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.9.3 Algorithm Design . . . . . . . . . . . . . . . . . . . . . 42
3.9.4 Dry Run . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.9.5 Practical Implementation . . . . . . . . . . . . . . . . . 43
3.10 List of Assignments . . . . . . . . . . . . . . . . . . . . . . . . 44
4 Signal 45
4.1 Signal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
4.1.1 Signal Introduction / Concepts . . . . . . . . . . . . . 45
4.1.2 Where Signals Come From . . . . . . . . . . . . . . . . 46
4.2 How Programs Responds to Signals . . . . . . . . . . . . . . . 46
4.3 Handling Signals . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.3.1 Writing Your Own Signal Handler . . . . . . . . . . . . 47
4.3.2 Signal in Signal Handler . . . . . . . . . . . . . . . . . 48
4.4 signal.h and Signal Related Functions . . . . . . . . . . . . . . 48
4.4.1 raise() . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.4.2 alarm() . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.4.3 pause() . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
4.5 Signal and Interrupts . . . . . . . . . . . . . . . . . . . . . . . 50
4.6 Process Termination and Exit Codes . . . . . . . . . . . . . . 50
4.7 Practice - 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.7.1 Prerequisite . . . . . . . . . . . . . . . . . . . . . . . . 50
4.7.2 Objective . . . . . . . . . . . . . . . . . . . . . . . . . 50
4.7.3 Algorithm Design . . . . . . . . . . . . . . . . . . . . . 51
4.7.4 Dry Run . . . . . . . . . . . . . . . . . . . . . . . . . . 54
4.7.5 Practical Implementation . . . . . . . . . . . . . . . . . 54
4.8 List of Assignments . . . . . . . . . . . . . . . . . . . . . . . . 56
5 Threads 57
5.1 Introducation to Threads . . . . . . . . . . . . . . . . . . . . . 57
5.1.1 What is Thread . . . . . . . . . . . . . . . . . . . . . . 57
5.1.2 Why Threads . . . . . . . . . . . . . . . . . . . . . . . 58
5.1.3 Advantages of Threads . . . . . . . . . . . . . . . . . . 59
5.2 Multi Threaded Environment . . . . . . . . . . . . . . . . . . 60
5.3 Process and Thread . . . . . . . . . . . . . . . . . . . . . . . . 60
5.4 What is a pthread . . . . . . . . . . . . . . . . . . . . . . . . 61
5.5 When to Use Threading . . . . . . . . . . . . . . . . . . . . . 61
5.6 Thread Creation . . . . . . . . . . . . . . . . . . . . . . . . . 62
5.7 Passing Data to Thread . . . . . . . . . . . . . . . . . . . . . 63
5.8 Returning Values From Threads . . . . . . . . . . . . . . . . . 63
6 Synchronization 73
6.1 What is Synchronization . . . . . . . . . . . . . . . . . . . . . 73
6.2 Why Synchronization . . . . . . . . . . . . . . . . . . . . . . . 74
6.2.1 Race Condition . . . . . . . . . . . . . . . . . . . . . . 74
6.2.2 Critical Section . . . . . . . . . . . . . . . . . . . . . . 74
6.3 Mutexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
6.3.1 What is Mutex . . . . . . . . . . . . . . . . . . . . . . 75
6.3.2 Creating / Destroying Mutexes . . . . . . . . . . . . . 75
6.3.3 Locking / Unlocking Mutexes . . . . . . . . . . . . . . 76
6.3.4 Deadlocks and Starvation . . . . . . . . . . . . . . . . 77
6.3.5 Priority Inversion . . . . . . . . . . . . . . . . . . . . . 78
6.3.6 Types of Mutexes and Mutex Attributes . . . . . . . . 79
6.3.7 Non-Blocking Mutex Tests . . . . . . . . . . . . . . . . 79
6.4 Semaphores for Threads . . . . . . . . . . . . . . . . . . . . . 80
6.5 Practice - 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.5.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . 81
6.5.2 Objective . . . . . . . . . . . . . . . . . . . . . . . . . 81
6.5.3 Algorithm Design . . . . . . . . . . . . . . . . . . . . . 82
6.5.4 Dry Run . . . . . . . . . . . . . . . . . . . . . . . . . . 85
6.5.5 Practical Implementation . . . . . . . . . . . . . . . . . 85
6.6 List of Assignments . . . . . . . . . . . . . . . . . . . . . . . . 86
7 LINUX IPC 87
7.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
7.2 Pipe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
7.2.1 Creating Pipes . . . . . . . . . . . . . . . . . . . . . . 88
7.2.2 Properties . . . . . . . . . . . . . . . . . . . . . . . . . 88
7.2.3 Process Communication Using Pipes . . . . . . . . . . 89
7.2.4 Limitations of Pipes . . . . . . . . . . . . . . . . . . . 91
7.3 FIFOs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
7.3.1 Properties . . . . . . . . . . . . . . . . . . . . . . . . . 92
7.3.2 Creating a FIFO . . . . . . . . . . . . . . . . . . . . . 92
7.4 Shared Memory . . . . . . . . . . . . . . . . . . . . . . . . . . 93
7.4.1 Allocation . . . . . . . . . . . . . . . . . . . . . . . . . 93
7.4.2 Attachment and Detachment . . . . . . . . . . . . . . . 94
7.4.3 Controlling and Deallocating Shared Memory . . . . . 94
7.5 Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
7.5.1 Allocation . . . . . . . . . . . . . . . . . . . . . . . . . 95
7.5.2 Deallocation . . . . . . . . . . . . . . . . . . . . . . . . 96
7.5.3 Initialization . . . . . . . . . . . . . . . . . . . . . . . . 96
7.5.4 Wait and Post operations . . . . . . . . . . . . . . . . 97
7.6 List of Assignments . . . . . . . . . . . . . . . . . . . . . . . . 98
1.2 OS Basics
An operating system, or OS, is a software program that enables the computer
hardware to communicate and operate with the computer software. OS are
found on almost any device that contains a computer with multiple programs
from cell phones and video game consoles to super computer and web servers.
It makes sure that different programs and users running at the same time
do not interfere with each other. The operating system is also responsible
for security, ensuring that unauthorized users do not access the system.
Unix was primarily oriented towards the command line interface, and
that legacy is carried on in Linux. Thus, the graphical user interface with its
windows, icons and menus are built on top of a basic command line interface.
Furthermore, this means that the Linux file system is structured to be easily
manageable and accessible from the command line.
Notes:
• Linux is scalable
• The Linux OS and most Linux applications have very short debug-times
Notes:
Notes:
1.4.2 OS Services
These are services that are typically considered part of the operating system
(e.g. windowing system, command shell)
Notes:
1.4.4 Hardware
Notes:
Notes:
• determine which process will have access to the CPU and effect the
transfer between running processes
Notes:
Supporting multiple users of memory, there are times when the available
memory can be exhausted. For this reason, pages can be moved out of
memory and onto the disk. This process is called swapping because the
pages are swapped from memory onto the hard disk.
Notes:
1.7.2 FEATURES:
• Block fragmentation
• Logical deletion
• Journaling
Notes:
Notes:
Notes:
Notes:
System Calls
Kernel Space is where Kernel executes and provide its services.User space
is memory locations where user processes (everything other than kernel) runs.
13
• Process Control
• File Mangement
• Device Management
• Information Maintainance
• Communication
Notes:
A call to a library function is just like any other function call.The argu-
ments are placed in processor registers or onto the stack, and execution is
transferred to the start of the functions code, which typically resides in a
loaded shared library.
Notes:
Eg : strace ls
Notes:
• close
• read
• write
• lseek
• fcntl
• dup
• dup2
Notes:
• time
• gettimeofday
• localtime
• ctime
• strftime
Notes:
• nanosleep
Notes:
2.4 Practice - I
W.A.P to copy a file to another using system calls.
2.4.1 Prerequisites
1. File related system calls
2.4.2 Objective
1. Familiarising commonly used file related system calls.
yes
exit 1 argc < 3
no
fd=open file1
for reading
yes
exit 1 fd=-1
no
fd2=open new
file2 for writing
no
If fd2 = -1
yes
no
exit 1 If file exists
yes
overwrite(y/n)?
no
exit 1 If y
yes
read the fd
BUFF_SIZE size
no If read
exit 0
success
yes
write the read
contents to fd2
yes
no if write
exit 0
success
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
Processes
3.1 Processes
3.1.1 What is a Process?
Running Instance of a Program is called a Process.
A process competes for system resources and CPU with other processes.
Once it gains control of the CPU, it runs a program within its own address
space. The execution of a process is independent of the execution of the oth-
ers, and it cannot read or write data into the address space of other processes.
25
Notes:
Notes:
3.3 Schedular
The assignment of physical processors to processes allows processors to ac-
complish work. The problem of determining when processors should be as-
signed and to which processes is called processor scheduling or CPU schedul-
ing.
When more than one process is runable, the operating system must decide
which one first. The part of the operating system concerned with this de-
cision is called the scheduler, and algorithm it uses is called the scheduling
algorithm. All the scheduling algorithms are discussed in the process schedul-
ing chapter.
Notes:
3.3.1 Operations
• create a process, adding it to the set of ready processes
• destroy a process
Notes:
TASK INTERRUPTIBLE
The process is sleeping (that is, it is blocked), waiting for some condition
to exist. When this condition exists, the kernel sets the process’s state
to TASK RUNNING. The process also awakes prematurely and becomes
runnable if it receives a signal.
Notes:
TASK UNINTERRUPTIBLE
This state is identical to TASK INTERRUPTIBLE except that it does not
wake up and become runnable if it receives a signal. This is used in situa-
tions where the process must wait without interruption or when the event
is expected to occur quite quickly. Because the task does not respond to
signals in this state, TASK UNINTERRUPTIBLE is less often used than
TASK INTERRUPTIBLE.
Notes:
TASK STOPPED
Process execution has stopped; the task is not running nor is it eligible to
run. This occurs if the task receives the SIGSTOP, SIGTSTP, SIGTTIN, or
SIGTTOU signal or if it receives any signal while it is being debugged.
Notes:
TASK ZOMBIE
The task has terminated, but its parent has not yet issued a wait4() system
call. The task’s process descriptor must remain in case the parent wants to
access it. If the parent calls wait4(), the process descriptor is deallocated.
Notes:
3.4.2 Process ID
Every process has a process-ID, which is a positive integer. At any instant
this is guaranteed to be unique. Every process but one has a parent. The
exception is process 0, which is created and used by the kernel itself, for
swapping.
Notes:
PS fields
• S: process status (R: runnable, S: sleeping, T: suspended, Z: zombie)
• CMD: command
Notes:
• getppid()
Notes:
• top: Display the process that are using the most CPU
Notes:
Notes:
• Ready queue : set of all processes residing in main memory, ready and
waiting to execute
Notes:
system("wc -l");
Notes:
If the operation is successful, there are then both parent and child pro-
cesses and both see fork return, but with different values: it returns a value of
0 in the child process and returns the child’s process ID in the parent process.
The specific attributes of the child process that differ from the parent
process are:
3.6.3 vfork()
vfork() is designed to be used in the specific case where the child will exec()
another program, and the parent can block until this happens. A traditional
fork() required duplicating all the pages of the parent process in the child -
a significant overhead.
While fork makes a complete copy of the calling process’s address space
and allows both the parent and child to execute independently, vfork does
not make this copy. Instead, the child process created with vfork shares its
parent’s address space until it calls exit or one of the exec functions. In the
meantime, the parent process suspends execution.
Notes:
int main()
{
pid_t pid;
if (pid = fork())
{
---- do something ---- /* parent */
}
else
{
---- do something ---- /* child */
}
return 0;
}
• Pending alarms.
• Pending signals.
• Signals that are set to be ignored in the existing process image are also
set to be ignored in the new process image. All other signals are set to
the default action in the new process image.
Notes:
int main()
{
printf("calling ls -l\n");
execl("/bin/ls", "ls", "-l", NULL);
printf("exec fails\n");
}
• execlp
• execve
• execl
• execle
Notes:
Notes:
Pages in the parent’s region are not copied to the child’s region until
needed. Both parent and child can read the pages without being concerned
about sharing the same page. However, as soon as either parent or child
writes to the page, a new copy is written, so that the other process retains
the original view of the page.
Notes:
• waitpid
• waitid
• wait3
• wait4
pid t wait(int *status) : used to wait until any one child process termi-
nates.
wait (&status) If the exit status value of the child process is zero, then the
status value reported by waitpid or wait is also zero. You can test for other
kinds of information encoded in the returned status value using the macros
mentioned in man page of wait. These macros are defined in the header file
sys/wait.h.
Notes:
3.9 Practice - I
Write a program to show parent child relationships by using fork.
3.9.1 Prerequisites
1. Concepts of process and process creation.
3.9.2 Objective
1. Understanding the picture of process creation.
ret=fork()
ret>0 ret==0
return 0 return 0
( ) Try to prevent the child from becoming the zombie without actually
blocking on that
( ) Write a program to resume the process which has been stopped
( )
( )
( )
( )
( )
( )
( )
Emertxe Information Technologies Pvt Ltd. Copyright 2018
( )
Chapter 4
Signal
4.1 Signal
4.1.1 Signal Introduction / Concepts
Signalling is interrupt like mechanism. Its a way of sending simple messages
to a process or group of processes. Most of these messages are already defined
and can be found in <linux/signal.h>. However, signals can only be pro-
cessed when the process is in user mode. If a signal has been sent to a process
that is in kernel mode, it is dealt with immediately on returning to user mode.
There are a set of defined signals that the kernel can generate or that can
be generated by other processes in the system, provided that they have the
correct privileges. Each signal in Linux has got a name starting with ’SIG’
and a number associated with it.
45
Notes:
signal
signal(SIGALRM, wakeup);
alarm(10);
-------
-----doing some job -----
-------
While 10 seconds reached and process is still alive, wakeup function will
get invoked.
sigaction
sigaction() is another system call that manipulates signal handler. It is much
more advanced comparing signal().
Notes:
4.4.1 raise()
sends a signal to the executing process.
E.g. raise(int sig);
Notes:
4.4.2 alarm()
Schedules an alarm signal. Can cause a SIGALRM.
E.g. alarm(int sec);
Notes:
4.4.3 pause()
Function shall suspend the calling thread until delivery of a signal whose
action is either to execute a signal-catching or to terminate the process.
E.g. pause();
Notes:
4.7 Practice - 1
Write a program to produce alarm. While alarm time expires, create an
interface for reseting the alarm or for exiting from the program.
4.7.1 Prerequisite
1. signal system call concepts
4.7.2 Objective
1. Implementing concepts of SIGALRM signal and time related functions.
Read alarm
Time from user
Prompt entered no
If valid
Time is invalid time
yes
register
Alarm handler
Alarm
Display date expires
Do some work
and time
no
new alarm
needed
yes
Read alarm
exit
Time from user
yes
If valid
time
no
( ) Kill the process by signal & try to get the signal number
programatically
( ) Handle the signal in process without using a sigaction function
( )
( )
( )
( )
( )
( )
( )
Threads
57
• That thread can create additional threads; all these threads run the
same program in the same process, but each thread may be executing
a different part of the program at any given time.
• Stack pointer
• Registers
Notes:
• All threads within a process share the same address space. Inter-thread
communication is more efficient and in many cases, easier to use than
inter-process communication.
• Overlapping CPU work with I/O: For example, a program may have
sections where it is performing a long I/O operation. While one thread
is waiting for an I/O system call to complete, CPU intensive work can
be performed by other threads.
Notes:
Notes:
• Less time to switch between two threads within the same process
Notes:
All thread functions and data types are declared in the header file <pthread.h>.
The pthread functions are not included in the standard C library. Instead,
they are in libpthread, so you should add -lpthread to the command line
when you link your program.
Notes:
int pthread create(pthread t *tid, const pthread attr t *attr, void*(*start routine)(void
*), void *arg);
int main()
{
pthread_t tid;
pthread_create(&tid, NULL, my_thread_func, NULL);
while(1)
;
return 0;
}
The pthread create() function is called with attr having the necessary
state behavior. start routine is the function with which the new thread be-
gins execution. When start routine returns, the thread exits with the exit
status set to the value returned by start routine.
This function shall suspend the calling thread until the targeted thread
terminates. When value ptr is non-NULL, then value ptr shall contain the
value returned by thread.
Following are some of the attributes that are specific to each thread :
• the thread ID, thread attribute, start routine, argument and return
value
• errno
Notes:
• Priority
• Stack size
• Name
• Thread group
• Detach state
• Scheduling policy
• Inherit scheduling
Notes:
The function pthread detach() can be called from any thread, in particular
from within the thread to detach (any thread can obtain its own thread ID
using the pthread self() API).
pthread_attr_t attr;
int main()
{
pthread_t tid;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&tid, &attr, my_thread_func, NULL);
pthread_join(tid, NULL);
}
Notes:
pthread_t tid;
tid = pthread_self();
Notes:
int status;
pthread_exit(&status); /* exit with status */
The pthread exit() function terminates the calling thread. All thread-
specific data bindings are released. If the calling thread is not detached,
then the thread’s ID and the exit status specified by status are retained
until the thread is waited for (blocked). Otherwise, status is ignored and the
thread’s ID can be reclaimed immediately.
Notes:
pthread_t thread;
int ret;
ret = pthread_cancel(thread);
How the cancellation request is treated depends on the state of the target
thread. Two functions,
pthread setcancelstate() and pthread setcanceltype() determine that state.
Notes:
Notes:
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
Synchronization
One thread might run for a very long time, or the system might switch
among threads very quickly.
There is no way to make the system schedule the threads exactly the
same way it did before.
Notes:
73
These bugs are called race conditions; the threads are racing one another
to change the same data structure.
Notes:
The characteristic properties of the code that form a Critical Section are
• Codes that alter one or more variables that are possibly being refer-
enced in read-updata-write fashion by another thread.
• Codes use a data structure while any part of it is possibly being altered
by another thread.
Notes:
6.3 Mutexes
6.3.1 What is Mutex
The solution to the race condition problem is to let only one thread access
the resource at a time.
A mutex is a special lock that only one thread may lock at a time.
If a thread locks a mutex and then a second thread also tries to lock the
same mutex, the second thread is blocked, or put on hold.
Only when the first thread unlocks the mutex is the second thread un-
blockedallowed to resume execution.
Notes:
pthread_mutex_t mut;
int main()
{
pthread_mutex_init(&mut, NULL);
pthread_create(*tid, NULL, my_thread_func, NULL);
pthread_join(tid, NULL);
return 0;
}
Notes:
• If the mutex was unlocked, it becomes locked and the function returns
immediately.
• If the mutex was locked by another thread, pthread mutex lock blocks
execution and returns only eventually when the mutex is unlocked by
the other thread.
• More than one thread may be blocked on a locked mutex at one time.
• When the mutex is unlocked, only one of the blocked threads is un-
blocked and allowed to lock the mutex; the other threads stay blocked.
This function should always be called from the same thread that locked
the mutex.
Notes:
Consider there is a task L, with low priority. This task requires resource
R. Consider that L is running and it acquires resource R. Now, there is an-
other task H, with high priority. This task also requires resource R. Consider
H starts after L has acquired resource R. Now H has to wait until L re-
linquishes resource R. Everything works as expected up to this point, but
problems arise when a new task M starts with medium priority during this
time.
Notes:
Recursive mutex - safely be locked many times by the same thread. The
mutex remembers how many times pthread mutex lock was called on it by
the thread that holds the lock; that thread must make the same number
of calls to pthread mutex unlock before the mutex is actually unlocked and
another thread is allowed to lock it.
6.5 Practice - 1
Write a multi threaded program to calculate the average of numbers in an
array.
6.5.1 Prerequisites
1. Thread creation concepts.
6.5.2 Objective
1. Implementing synchronization between threads.
MAX_COUNT=5
create n number
of threads
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
LINUX IPC
7.1 Introduction
Interprocess communication (IPC) is the transfer of data among processes.
The types of inter process communication are:
• Pipes - Unnamed pipes set up by the shell normally with the ”|” char-
acter to route output from one program to the input of another.
• FIFOS - Named pipes operating on the basis of first data in, first data
out.
Notes:
87
7.2 Pipe
Pipe is used for one-way communication of a stream of bytes.
To send data to the pipe, we use the write() system call, and to retrieve
data from the pipe, we use the read() system call. Remember, low-level file
I/O system calls work with file descriptors! However, keep in mind that cer-
tain system calls, such as lseek(), do not work with descriptors to pipes.
int pfd[2];
pipe(pfd);
Pipe can be used to connect the standard output of one process to the
standard input of another.They provide a method of one-way communica-
tions (hence the term half-duplex) between processes.
ls | sort | lp
The above sets up a pipeline, taking the output of ls as the input of sort,
and the output of sort as the input of lp.
Notes:
7.2.2 Properties
Pipe does a destructive read, which means that the data once read from the
pipe cannot be retrieved. A pipe has a finite size, always atleast 4K.
Notes:
Notes:
A single process would not use a pipe. They are used when two processes wish
to communicate in a one-way fashion. A process splits in two using fork().
A pipe opened before the fork becomes shared between the two processes.
Before fork
After fork
This gives two read ends and two write ends. The read end of the pipe will
not be closed until both of the read ends are closed, and the write end will
not be closed until both the write ends are closed.
Either process can write into the pipe, and either can read from it. Which
process will get what is not known.
For predictable behaviour, one of the processes must close its read end,
and the other must close its write end. After fork
Suppose the parent wants to write down a pipeline to a child. The parent
closes its read end, and writes into the other end. The child closes its write
end and reads from the other end.
When the processes have ceased communication, the parent closes its
write end. This means that the child gets eof on its next read, and it can
close its read end.
#include <stdio.h>
if (pipe(pfd) == -1)
{
perror("pipe failed");
exit(1);
}
if ((pid = fork()) < 0)
{
perror("fork failed");
exit(2);
}
if (pid == 0)
{
/* child */
close(pfd[1]);
while ((nread = read(pfd[0], buf, SIZE)) != 0)
printf("child read %s\n", buf);
close(pfd[0]);
}
else
{
/* parent */
close(pfd[0]);
strcpy(buf, "hello...");
/* include null terminator in write */
write(pfd[1], buf,
strlen(buf)+1);
close(pfd[1]);
}
exit(0);
}
Notes:
7.3 FIFOs
Fifos are named pipes.
Notes:
7.3.1 Properties
• Named pipes exist as a device special file in the file system.
• When all I/O is done by sharing processes, the named pipe remains in
the file system for later use.
Notes:
mknod MYFIFO p
mkfifo a=rw MYFIFO
Notes:
7.4.1 Allocation
shmget() is used to obtain access to a shared memory segment. It is proto-
typed by:
int shmget(key t key, size t size, int shmflg);
The key argument is a access value associated with the semaphore ID.
The size argument is the size in bytes of the requested shared memory. The
shmflg argument specifies the initial access permissions and creation control
flags.
When the call succeeds, it returns the shared memory segment ID. This
call is also used to get the ID of an existing shared segment (from a process
requesting sharing of some existing memory portion).
int shm_id;
shm_id = shmget(key, 1024, IPC_CREAT);
Notes:
void *ptr;
ptr = shmat(shm_id, 0, 0);
-------
---do some work ---
-------
shmdt(ptr);
Notes:
Notes:
7.5 Semaphores
Semaphores can best be described as counters used to control access to shared
resources by multiple processes. They are most often used as a locking mech-
anism to prevent processes from accessing a particular resource while another
process is performing operations on it.
Notes:
7.5.1 Allocation
• The calls semget and semctl allocate and deallocate semaphores
int main()
{
int semid;
semid = semget(key, 2, IPC_CREAT|0600);
}
Notes:
7.5.2 Deallocation
• Semaphores continue to exist even after all processes using them have
terminated.
int main()
{
/* Allocate and get semid */
semctl(semid, 0, IPC_RMID);
}
Notes:
7.5.3 Initialization
• To initialize a semaphore, use semctl with zero as the second argument
and SETALL as the third argument.
• For the fourth argument, you must create a union semun object and
point its array field at an array of unsigned short values.
int main()
{
/* Allocate */
/* Deallocate */
}
Notes:
int main()
{
/* Allocate */
/* Initialise */
/* Deallocate */
}
Notes:
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
( )
99
struct sockaddr_in
{
short sin_family; // e.g. AF_INET
unsigned short sin_port; // e.g. htons(3490)
struct in_addr sin_addr; // see struct in_addr, below
char sin_zero[8]; // zero this if you want to
};
struct in_addr
{
unsigned long s_addr; // that’s a 32-bit long, or 4 bytes
};
Hands on:
1. Open sys/types.h and sys/socket.h in the Linux and read through the
definitions
• int send(int sockfd, const void *msg, int len, int flags);
• int recv(int sockfd, void *buf, int len, unsigned int flags);
• int sendto(int sockfd, const void *msg, int len, unsigned int flags, const
struct sockaddr *to, socklen t tolen);
• int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct
sockaddr *from, int *fromlen);
• close(sockfd);
• int setsockopt(int s, int level, int optname, const void *optval, socklen t
optlen);
struct timeval
{
int tv_sec; // seconds
int tv_usec; // microseconds
};
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int main(void)
{
struct timeval tv;
fd_set readfds;
tv.tv_sec = 2;
tv.tv_usec = 500000;
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
if (FD_ISSET(STDIN, &readfds))
printf("A key was pressed!\n");
else
printf("Timed out.\n");
return 0;
}
service <service_name>
{
<attribute> <assign_op> <value> <value>
}
service SMTP
{
socket type = stream
protocol = tcp
wait = no
user = mail
server = /usr/sbin/exim
}
client should parse it and find out the port number and IP address of the
server. Depending on the service it requires it sends the appropriate ’server
request’ packets and get the ’server reply’ packets back.
Relay-agent: The relay agents act in between the clients and servers. They
have a database of server information and would provide to the clients, when
clients send a ’relay request’ packet. The relay agent would search through
its database for the required service and send back the response in the ’relay
reply’ packet. The database is again a dynamically created and data struc-
tures library must be used for the same.
Implementation details:
3. There should be relay request, relay reply, service request(s) and service
reply(s) packets should be defined.
example, sitting in India the administrator may want to monitor the enter-
prise server that is kept in Russia. The adminis- trator would send the remote
command and the external entity would reply back with the output of the
command. This assignment is to implement the remote command execution
using Linux environment.
The UDP client would send any standard Linux shell command (say ’ls’)
using the ’command request’ packet along with the number of times the com-
mand needs to be executed. At the server side the server would parse the
command the execute it the number of times specified. Apart from ex- ecut-
ing it, the server would capture the output in a file. This file would be then
read by the server and the output would be sent back to the client in terms
of 64 bytes of ’data’ packets along with the packet number. If the data size
is less then 64 bytes it needs to be specified by the server. As this connection
is unreliable UDP connection the client should acknowledge back with and
ACK packet along with the packet number. The server would send the next
packet only after receiving the successful ACK for the previous packet.
Implementation details:
guments a server name or IP address and a port number.Your client will use
select() to determine if data is ready to be read from the keyboard.Any line
typed on the keyboard should be sent to the server (using sendto() API).
Any datagrams received from the server (recvfrom()) should be printed (dis
played). Maximum message/buffer length is 1024 bytes. For example:
Process Management
Notes:
111
CPU & I/O Burst Cycle Process execution consists of a cycle of CPU
execution and I/O wait.
Notes:
• 4.Terminates.
• Pre-Emptive
• Priority based
• RR-Time slice
• RR-Priority based
• Pre-emptive
Notes:
Notes:
• The average waiting time under the FCFS policy is often quite long.
• FCFS is non-preemptive.
example :
Consider the following set of processes that arrive at time 0, with the length
of the CPU burst given in milliseconds:
P1 5
P2 3
Notes:
Notes:
example :
Consider the following set of processes that arrive at time 0, with the length
of the CPU burst given in milliseconds:
Process Burst time
P1 24
P2 3
P3 3
Notes:
Notes:
9.6.6 Pre-emption
Pre-emption means while a lower priority process is executing on the proces-
sor another process higher in priority than comes up in the ready queue, it
preempts the lower priority process.
Notes:
The time quantum value is the maximum CPU time portion assigned to
the process in that epoch.When a process has exhausted its time quantum,
it is preempted and replaced by another runnable process.If it suspends itself
to wait for I/O, it preserves some of its time quantum and can be selected
again during the same epoch.
The epoch ends when all runnable processes have exhausted their quanta;Then
the scheduler algorithm recomputes the time-quantum durations of all pro-
cesses and a new epoch begins.
Notes:
Memory Management
10.1 Introduction
The memory management subsystem is one of the most important parts of
the operating system. Since the early days of computing, there has been a
need for more memory than exists physically in a system. Strategies have
been developed to overcome this limitation and the most successful of these
is virtual memory. Virtual memory makes the system appear to have more
memory than it actually has by sharing it between competing processes as
they need it.
Notes:
121
• Protection
• Sharing
Notes:
To make this translation easier, virtual and physical memory are divided
into handy sized chunks called pages.
Notes:
Notes:
10.4.2 Paging
Paging is the most common memory management technique:
Notes:
• finally, return physical address (frame number * page size + page offset)
Notes:
Notes:
Notes:
Notes:
10.5 Swapping
If a process needs to bring a virtual page into physical memory and there are
no free physical pages available, the operating system must make room for
this page by discarding another page from physical memory.
The operating system must preserve the contents of that page, if the page
is modified, so that it can be accessed at a later time. This type of page is
known as a dirty page and when it is removed from memory it is saved in a
special sort of file called the swap file.
Linux uses a Least Recently Used (LRU) page aging technique to fairly
choose pages which might be removed from the system. This scheme involves
every page in the system having an age which changes as the page is accessed.
The more that a page is accessed, the younger it is; the less that it is accessed
the older and more stale it becomes. Old pages are good candidates for
swapping.
Notes:
Assignment Guidelines
133
Grading of Programming
Assignments
• You get 4 points if the program does exactly what it is supposed to do.
• Two (2) points are reserved for the ease of use, the type of user interface,
the ability to handle various user input errors, or any extra features that
your program might have.
135