Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
100% found this document useful (1 vote)
235 views

BIT 4205 - Network Programming - Updated - Complete Notes

Mount Kenya University Network programming pdf notes

Uploaded by

Derick Ajwang'
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
235 views

BIT 4205 - Network Programming - Updated - Complete Notes

Mount Kenya University Network programming pdf notes

Uploaded by

Derick Ajwang'
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 99

P.O.

Box 342-01000 Thika


Email: info@mku.ac.ke
Web: www.mku.ac.ke

SCHOOL OF PURE AND APPLIED SCIENCES

DEPARTMENT OF INFORMATION
TECHNOLOGY
COURSE CODE: BIT 4206

COURSE TITLE: NETWORK PROGRAMMING

Instructional Manual for BBIT – Distance Learning

Prepared by Mr. Paul Mutinda


E-mail: mutindaz@yahoo.com

1|Page
COURSE OUTLINE

BIT 4206 Network Programming


Contact Hours 42
Pre-requieste BIT 3102 NETWORK MANAGEMENT , BIT 3201 Object
Oriented Programming
Purpose To create awareness of the role and impact of ICT in business
Objectives By the end of the course unit a learner shall be able to:
 Have knowledge about Unix technologies (IPC, POSIX threads, Unix filesystem.
 Be able to develop client-server network applications on the Internet, based on UNIX/Linux
Course Content
An overview of C++ - the language; Inheritance, Polymorphism, Encapsulation, Templates, Dynamic
memory management, Handling Exception
An overview Unix technologies, POSIX Threads (p-threads), Creating and destroying thread:, Creating,
destroying threads., Send parameters to threads., Thread Synchronization:, Semaphore., Mutex, Condition
variable., Thread Models:, Thread Pool – Boss/worker., Pipeline., Background task., A thread pool
implementation.
The Unix file system, Basic I/O, General Unix File System Structure, - Standard "C" File Read And Write
Network programming, Introduction to socket, Types of socket , TCP socket programming model, Socket
I/O: socket, bind, listen, accept, connect, send, recv, Utilities: byte-ordering, network address, Issue:
Blocking-Non blocking, Client sample, Server sample

Teaching Methodology Lectures

Instructional materials/Equipment
Audio visual aids in lecture rooms, Computer in the computer laboratories.
Assessments
A learner is assessed through ;
Continuous Assessment Tests (CATs) (30%), End of semester examination (70%)

Required text books

2|Page
Stephens R., Fenner B, Rudoff A, (2003) Unix Network Programming, Volume 1:
The Sockets Networking API (3rd Edition)
Graba. J. (2007), An Introduction to Network Programming with Java, Addison-Wesley
Text books for further reading
Jorgensen B., (2009) Beej's Guide to Network Programming Using Internet
Sockets
Other support materials
 Various application manuals and journals.
 Variety of electronic resources as may be prescribed by the lecturer.

3|Page
Table of Contents
INTRODUCTION UNIX TECHNOLOGIES .............................................................................................................................. 8

Operating systems Basics .............................................................................................................................................. 8

Virtual Machine Abstraction ......................................................................................................................................... 8

What is UNIX? ................................................................................................................................................................ 9

Unix Architecture: ................................................................................................................................................... 10

Here is a basic block diagram of a UNIX system: ...................................................................................................... 10

Fig: UNIX Architecture............................................................................................................................................... 12

The Kernel ................................................................................................................................................................... 12

Fig: UNIX Kernel ........................................................................................................................................................ 13

Kernel functions: ......................................................................................................................................................... 13

• Memory management ............................................................................................................................................... 13

• Process scheduling .................................................................................................................................................... 13

• File management and security ................................................................................................................................... 13

• Interrupt handling and error reporting....................................................................................................................... 13

The Shell: .................................................................................................................................................................... 14

Review Questions ........................................................................................................................................................ 19

UNIX SYSTEM CALLS ........................................................................................................................................................ 20

System Call Interface ................................................................................................................................................... 20

Kernel mode ................................................................................................................................................................ 20

Library calls and system calls ....................................................................................................................................... 21

Anatomy of a System call ............................................................................................................................................ 22

Handling System call................................................................................................................................................ 23

A system call Error ................................................................................................................................................... 24

File creat() system call ............................................................................................................................................. 25

4|Page
PROCESS MANAGEMENT ................................................................................................................................................ 29

What is process? ......................................................................................................................................................... 29

Process Manager ..................................................................................................................................................... 29

System calls for shared memory -shmget() ............................................................................................................. 42

 shmget()- creates a shm segment ......................................................................................................................... 42

 Creating a shared segment or getting its ID ........................................................................................................ 42

System calls for Attaching to shared memory - Shmat() ......................................................................................... 44

Process Synchronization .............................................................................................................................................. 48

Race Conditions ....................................................................................................................................................... 48

POSIX THREADS PROGRAMMING.................................................................................................................................... 51

Pthreads Overview ...................................................................................................................................................... 51

Pthreads Overview ...................................................................................................................................................... 53

What are Pthreads? ................................................................................................................................................. 53

Why Pthreads? ......................................................................................................................................................... 54

Designing Threaded Programs .................................................................................................................................... 56

Parallel Programming: ............................................................................................................................................. 56

The Pthreads API..................................................................................................................................................... 60

Thread Management ................................................................................................................................................... 62

Creating and Terminating Threads .............................................................................................................................. 62

Routines:.................................................................................................................................................................. 62

Creating Threads: .................................................................................................................................................... 62

Thread Binding and Scheduling: .............................................................................................................................. 64

Terminating Threads ............................................................................................................................................... 64

Example: Pthread Creation and Termination .............................................................................................................. 65

Passing Arguments to Threads .................................................................................................................................... 66

Joining and Detaching Threads.................................................................................................................................... 69


5|Page
Example: Pthread Joining ............................................................................................................................................ 71

Mutex Variables........................................................................................................................................................... 72

Overview.................................................................................................................................................................. 72

Creating and Destroying Mutexes ........................................................................................................................... 74

Locking and Unlocking Mutexes .............................................................................................................................. 75

Example: Using Mutexes ............................................................................................................................................. 76

Condition Variables ..................................................................................................................................................... 79

Overview ..................................................................................................................................................................... 79

Creating and Destroying Condition Variables ............................................................................................................ 80

Waiting and Signaling on Condition Variables ............................................................................................................ 81

Example: Using Condition Variables .......................................................................................................................... 82

References ................................................................................................................................................................... 84

SOCKET PROGRAMMING ................................................................................................................................................. 85

Introduction to sockets ............................................................................................................................................... 85

Socket characteristics: ............................................................................................................................................. 85

Prerequisites for socket programming ........................................................................................................................ 86

How sockets work ....................................................................................................................................................... 86

Socket characteristics .............................................................................................................................................. 88

Types socket connections ........................................................................................................................................ 88

Sockets and socket addresses ...................................................................................................................................... 89

Sockets .................................................................................................................................................................... 89

Socket descriptors ................................................................................................................................................... 90

Socket creation & binding ........................................................................................................................................... 90

Creating a Socket ..................................................................................................................................................... 90

Binding a socket to a port - bind () ......................................................................................................................... 91

Network connection establishment ............................................................................................................................ 92


6|Page
Connection-oriented (e.g.TCP) ................................................................................................................................ 92

How to compile and Run socket program ............................................................................................................... 96

References ................................................................................................................................................................... 96

SAMPLE EXAMINATIONS ................................................................................................................................................. 96

7|Page
INTRODUCTION UNIX TECHNOLOGIES

Operating systems Basics


An operating system is a suite of programs that control a Computer-system.

A Computer system consists of one or more CPUs, device controllers, shared memory connected through a common
bus.

Every piece of hardware is different, but the OS abstracts this disparity to give the user a unified interface that is easy
to use.

Virtual Machine Abstraction

Primary Objectives of OS:

-Making a computer system convenient to use: by hiding the details of the hardware resources from the user
provides him/her with a convenient interface.

-Resource management

Each OS component (e.g. file systems, virtual memory, networking, scheduling):

What‟s the hardware interface? (Physical reality)

What‟s the application interface? (Nicer abstraction) Systems software

Systems software help create abstraction and a uniform interface for programs to use when requesting for OS
services. Examples of systems software:
8|Page
Assemblers

Compilers

Linkers

The dichotomy of programming

Application programming: targeted toward developing systems to support the end-user.

Systems programming: targeted toward developing systems to support the programmer.

Recently, this boundary has become fuzzy.

Building a web browser, such as Google Chrome might once have been considered application
programming.

However, nowadays developing such applications requires attention to system details such as resources and
efficiency (e.g., Google Chrome is multi-threaded).

Systems programming

Historically, systems programming meant programming the system (i.e., building compilers, shells, loaders,
and so on).

However, nowadays, systems programming has come to mean programming with the system (i.e., making
system calls, managing threads, and so on).

Systems programming requires a greater awareness of issues of hardware and efficiency than application
programming.

It also requires knowledge of low level languages that provides direct access to and control of system
resources; this leads us to UNIX and C

What is UNIX?
The UNIX operating system is a set of programs that act as a link between the computer and the user.

The computer programs that allocate the system resources and coordinate all the details of the computer's
internals is called the operating system or kernel.

Users communicate with the kernel through a program known as the shell. The shell is a command line
interpreter; it translates commands entered by the user and converts them into a language that is understood
by the kernel.

Unix was originally developed in 1969 by a group of AT&T employees at Bell Labs, including Ken
Thompson, Dennis Ritchie, Douglas McIlroy, and Joe Ossanna.
9|Page
There are various Unix variants available in the market. Solaris Unix, AIX, UP Unix and BSD are few
examples. Linux is also a flavor of Unix which is freely available.

Several people can use a UNIX computer at the same time; hence UNIX is called a multiuser system.

A user can also run multiple programs at the same time; hence UNIX is called multitasking.

Unix Architecture:

Here is a basic block diagram of a UNIX system:

The main concept that unites all versions of UNIX is the following four basics:

• Kernel: The kernel is the heart of the operating system. It interacts with hardware and most of the tasks like memory
management, tash scheduling and file management.

• Shell: The shell is the utility that processes your requests. When you type in a command at your terminal, the shell
interprets the command and calls the program that you want.

The shell uses standard syntax for all commands. C Shell, Bourne Shell and Korn Shell are most famous shells which
are available with most of the Unix variants.

10 | P a g e
• Commands and Utilities: There are various command and utilities which you would use in your day to day
activities. cp, mv, cat and grep etc. are few examples of commands and utilities.

There are over 250 standard commands plus numerous others provided through 3rd party software. All the commands
come along with various optional options.

• Files and Directories: All data in UNIX is organized into files. All files are organized into directories. These
directories are organized into a tree-like structure called the file system.

UNIX has evolved over the past thirty years from its conceptual stage into a powerful and effective operating system
and the credit goes to the fundamental structure of UNIX, which is very robust due to its layered approach comprising
of the:

• Kernel

• Shell

• Utilities and applications

One of the most powerful and attractive features of UNIX is its file system, which manages data, stored on the
computer's secondary storage devices. The file system facilitates organizing stored information in a very logical way,
and manipulating it as and when required.

11 | P a g e
Fig: UNIX Architecture
The Kernel
> Core of the UNIX system

> Interacts directly with the hardware

> Insulates other parts of UNIX from hardware

> Performs all low level functions

> Parts of kernel deals with I/O devices, called Device Drivers

> All programs and applications interact with the kernel

12 | P a g e
Fig: UNIX Kernel
The kernel is the Core of the UNIX system, which controls the system hardware and performs various low
level functions. Viewing the operating system as a set of layers, the kernel usually refers to the operating
system itself.
However, the kernel does not directly deal with the user. Instead, it starts a separate program, called shell,
which actually interacts with the user and interprets the commands. The utilities and applications add
special capabilities to the operating system.
Kernel functions:
• Memory management
• Process scheduling
• File management and security
• Interrupt handling and error reporting
13 | P a g e
• Input / Output services
• Date and Time services
• System accounting
The Kernel:
• Controls the execution of processes
• Allows creation, termination, suspension and communication of process.
• Enforces the security scheme and prevents unauthorized access to stored information like files and
directories.
• Handles all low level input and output services.
• Handles the interrupts and system errors.
• Schedules the Central Processor and allocates system resources to each user of the system.
If the UNIX operating system is to be loaded on different hardware platforms, the kernel has to be
customized accordingly.
All applications and utilities including the shell interact with the kernel by invoking well-structured routines
of kernel by means of messages called system calls.
The Shell:
• Is the command interpreter of UNIX
• Interface between the kernel and the user
• Provides powerful programming capabilities
The shell is the interface between a user and the operating system. When any user logs in, a copy of the shell
program is started up, displaying a prompt sign such as '$' (dollar), which informs the user that the shell is
waiting to accept a command.
In UNIX, there are three types of shells:
1. The Bourne Shell
2. The C Shell
3. The Korn Shell
From the figures you can conceive the way; various parts and portions of UNIX are arranged around the
hardware. The core of UNIX is the kernel, which schedules jobs and manages data storage, and it is very

14 | P a g e
closely interfaced with hardware. The hardware functions according to the machine instructions released
ultimately by the kernel, based on the shell's interpretation of user commands.
Surrounding the kernel are parts of software of the shell relating to:
1. Execution of commands for piping and filtering actions.
2. Tools for carrying out foreground and background processing.
3. Utilities for configuring the hardware.
4. I/O redirection and command execution utilities.
5. Filename substitution.
The shell forms an interface between the user and the kernel. Outside the shell are the different user-specific
utilities of UNIX, numbering around 300, which enhance its capability.
Above this, are the user programs and application packages, which can facilitate data entry, data
modification, query, report generation, etc.

15 | P a g e
Figure: Shell functions
The shell is a program that collects and interprets the user commands, invokes the concerned program file
from memory and directs the kernel to execute them.
As the name shell suggests, the shell envelops the kernel. Externally, the UNIX operating system is made up
of two parts. One part is a large set of system programs, each one corresponding to a command, and another
part is the shell, which interprets, manages and coordinates the execution of these programs. Most of the
users are unaware of the various complexities of the operating system or the hardware.

16 | P a g e
The user sees the shell command as one peculating down the UNIX system, and the kernel, looking up to the
user through the shell- for the next set of process. This relationship and interface of the kernel with different
users is shown in the figure below.
Every user, once accepted by the kernel as authorized, is issued a shell prompt. Each user has his own shell
(a separate and personal copy for each user) and the commands issued by him is counted and numbered
serially. A separate shell procedure is reserved for each user.

Figure: UNIX interaction with the users

17 | P a g e
Command Execution
Refer figure below, which illustrates the cycle of command execution. To begin with, the kernel displays a
shell prompt after authorized login. The shell waits for the input from the user, decodes the command line
and searches for the program. If the program is found, the shell retrieves and submits it to the kernel to
execute the program.

The kernel delivers the output. If the command is not found, it signals the kernel to display command not
found at the terminal. The shell accepts the kernel's reply, and in both cases displays the next prompt. This
cycle continues until the user with <CTRL>
D or logout terminates it. Once the shell encounters end of input, it instructs the kernel to log out the user,
and displays the login message again.
The system directories where the command file programs are stored are the /bin and /usr/bin. On receipt of
the command, which is nothing but the executable filenames in the system directory, the shell locates them
and transfers control to the kernel to execute.
These filenames can be verified by the command pwd and Is, after changing to the directories Ibin and
/usrlbin.
Shell Environment
A separate shell process is apportioned to each user as stated earlier. The separate shell once created provides
an environment within which the user operates. The shell environment consists of the following to ensure
proper interaction between the user and the system:

18 | P a g e
1. The name of the users, and a working directory (a directory allotted to the user by the operating system).
2. A list of system directories to be searched to locate the commands given by the user.
3. The file access permission modes.
4. A record of users‟ identification (user id) and group identification number (group id).
Foreground and Background Processing
The shell can execute commands in the foreground and also in the background. Foreground commands
execute sequentially (one command cannot commence until execution of the preceding command has
completed execution). Foreground commands like editing a program or processing a text involves interaction
with the terminal and the input. Background processing jobs related commands are accompanied by &
(ampersand) symbol. Jobs like compiling, printing can be carried out as background jobs, since they do not
require any interaction with the user. There may be several background commands executed at a time. This
truly makes UNIX a multitasking system.

Review Questions
1. List the main functions of the kernel, and shell, respectively.
2. Explain the relation between UNIX commands and UNIX system filenames.
3. Define and explain system calls in UNIX, and explain how UNIX is made portable across various
platforms.
4. Sketch the cyclic process of executions of commands issued from the terminal, and various roles played
by the shell, kernel and hardware.
5. What does the shell environment contain with reference to every specific user interacting with UNIX.
6. What does background processing mean?
7. What do you mean by tools of UNIX, list the classification of tools and utilities?
8. Sketch the UNIX directory system listing the system directories and the functions of the files under them.
9. Sketch and explain the conceptual structure of UNIX system software layers.
10. Explain with a sketch, how a common user looks upon his interaction with hardware.

19 | P a g e
UNIX SYSTEM CALLS

System Call Interface


All operating systems provide service points through which programs request services form the kernel.

A system call is a mechanism used by an application to request for services from the kernel.

Processes can either be user or kernel initiated and can run either in user mode or kernel mode.

Kernel mode
Kernel mode processes can:

Enable/Disable interrupts.

Direct access to I/O devices.

Access to memory table.

User mode only has rights to user initiated processes.

20 | P a g e
Library calls and system calls
The difference between system calls and library calls is that:

System calls are provided by the system and are executed in the system kernel.They are entry points into the
kernel and are therefore NOT linked into your program. These are not portable calls.

Library calls include the ANSI C standard library and are therefore portable. These functions are linked into
your program. (Recall linking in programming)

Because system calls are part of the O/S, the program has to make a context switch to the kernel when they
are called and because of this, they have a high startup overhead. The upside is that the time executing these
routines is assigned to the OS and not the user program.

Calling standard library functions does not involve system call interface. However a library function may
initiate a system call which in turn issues a system call e.g. a call to printf() may invoke write() system call to
do output.

A system call always involves using system call interface and using the kernel of OS.

21 | P a g e
Anatomy of a System call
General form of a system call is as follows:

[Returned value] = system_call_name (parameters); (if any)

Where:

returned_value = nonnegative integer if OK, -1 if error (in this case error code is placed in external variable
errno)

22 | P a g e
Handling System call
General Syntax:

23 | P a g e
A system call Error
When a system call discovers and error, it returns -1 and stores the reason the called failed in an external
variable named "errno".

The "/usr/include/errno.h" file maps these error numbers to manifest constants, and it these constants that
you should use in your programs.

When a system call returns successfully, it returns something other than -1, but it does not clear "errno".

"errno" only has meaning directly after a system call that returns an error.

Using a library function perror();


24 | P a g e
When you use system calls in your programs, you should check the value returned by those system calls.

Furthermore, when a system call discovers an error, you should use the "perror()" subroutine to print a
diagnostic message on the standard error file that describes why the system call failed.

The syntax for "perror()" is:

void perror(string)

char string;

File creat() system call


 The prototype for the creat() system call is:
25 | P a g e
int creat(file_name, mode)
char *file_name;
int mode;

 Where:

 file_name is pointer to a null terminated character string that names the file.

 mode defines the file's access permissions. - read, write etc.

Example 1: creat() system call


/* creat.c */
#include <stdio.h>
#include <sys/types.h> /* defines types used by sys/stat.h */
#include <sys/stat.h> /* defines S_IREAD & S_IWRITE */
int main()
{
int fd;
fd = creat("datafile.dat", S_IREAD | S_IWRITE);
if (fd == -1)
printf("Error in opening datafile.dat\n");
else {
printf("datafile.dat opened for read/write access\n");
printf("datafile.dat is currently empty\n");
}
close(fd);
exit (0);
}

26 | P a g e
Example 2: use of fork() and exec() to create a new directory
/* newdir.c
create a new directory, called newdir, using fork() and
exec() */
#include <stdio.h>
int main()
{
int fd;
if ( fork() != 0)
wait ((int *) 0);
else {
execl ("/bin/mkdir", "mkdir", "newdir", (char *) NULL);
fprintf (stderr, "exec failed!\n");
exit (1);
}
/* now use newdir */
if ( (fd = open("newdir/foo.bar", O_RDWR|O_CREAT, 0644))== -1)
{
fprintf (stderr, "open failed!\n");
exit (2);
}
write (fd, "Hello, world\n", 14);
close (fd);
exit (0);
}

27 | P a g e
Categories of System Calls in Unix

28 | P a g e
PROCESS MANAGEMENT

What is process?
• The simplest definition of a process is that it is a program in execution on a computer.
• Another definition; a process the basic computational element in modern computer system.
• How does it differ from a program?
• A process consists of:

 Instructions to define the behavior of process.

 The data operated on by the process and the results it produces

 A set of resources to provide an environment for execution.

 A status record to keep track of the progress of the process during execution
• Each process uses resources to execute programs on data on Von Neumann computer.
• During execution, the process requests different resources according to the particular behavior defined by
the program
• Multiprogramming systems explicitly allow multiple processes to exist at any given time, where only one is
using the CPU at any given moment, while the remaining processes are performing I/O or are waiting for
resources.

Process Manager
• The process manager implements:

 The process abstraction by creating a model for the way the process uses the CPU and any system
resources.

 CPU sharing (scheduling), process synchronization mechanisms.

 Part of the Operating system‟s protection strategy.

The Process Model


• The scheduler moves process between execution "states”. A process‟ state defines what it can do.
• A process state consists of two elements:

 An address space (a subsection of the OS memory space where a process executes) and

29 | P a g e
 A set of registers (including PC and stack pointer).
The states are (roughly)

 New (waiting to be run first time)

 Running

 Ready (runnable)

 Blocked (waiting)

 Completed

Figure: Process states

Process Control Block


 PCB (also process descriptor) is a data block that describes the process to the operating system.

 With the PCB, the OS can manipulate all parts of a program's state.
PCB contents include

 Process execution state (what is the process currently doing?)

30 | P a g e
 Saved program counter (for processes not in running state). The counter indicates the address of the
next instruction to be executed for this process.

 Saved CPU register set (for processes not running) The registers vary in number and type, depending
on the computer architecture. They include accumulators, index registers, stack pointers, and
general-purpose registers, plus any condition-code information. Along with the program counter,
this state information must be saved when an interrupt occurs, to allow the process to be continued
correctly afterward

 Scheduling information (what priority, reason for sleep, etc.)

 Memory management book-keeping (where is the processes memory?) .

This information may include such information as the value of the base and limit registers, the page tables, or
the segment tables, depending on the memory system used by the operating system.
 Accounting information. This information includes the amount of CPU and real time used, time
limits, account numbers, job or process numbers, and so on.
 I/O status information: The information includes the list of I/O devices allocated to this process, a list
of open files, and so on.
 User id – the process owner.

 A PCB is needed because the OS does not always "pay attention" to a process so from the PCB, the
OS can determine what the process is doing, and how it should respond to some event.

 It also needed to allow OS to organize processes for example: disk I/O

Process switching (context switch)


 CPU switches between a running process and one that is runnable (i.e. on the ready queue).

 When this switching is so frequent that hardly is there any execution of the process it becomes an
overhead called a context switch overhead.

 A process will switch because of an interrupt or a trap.

 What‟s the difference?

31 | P a g e
Interrupts
 An interrupt is an “unplanned” function call to a system routine (aka, the interrupt handler)

 Unlike a normal function call, the interrupted thread cannot anticipate the control transfer or prepare
for it in any way

 Control is later returned to the main thread at the interrupted instruction

 Running process may be leaving up CPU for two reasons

 Time slice has expired (clock interrupt) => PCB goes on ready queue

 Process makes a blocking call => PCB goes on specified queue and state is set to blocked

Types Interrupts
 Several classes of interrupts exist:

 Program interrupts (trap), generated by a program such as an overflow, division by zero etc.

 Clock Interrupts, generated by the CPU clock.

 I/O interrupt, generated by I/O device

 H/W failure, caused by a failure e.g. power, or parity error.

Traps

32 | P a g e
 An interrupt is an exceptional event that is automatically handled by the interrupt handler.

 In the case of an overflow, memory addressing violation, and the use of privileged instruction in user
mode, the handler will abort the program

 These types of interrupts are called traps

 All traps are going to be considered synchronous interrupts since they are generated by the processor
itself when it encounters an error inside the code stream.
I/O Interrupts

 This type of interrupt occurs when a device sends a signal to inform the CPU that an I/O operation
has been completed.

 An I/O flag is used to handle this type of interrupt

 When an I/O interrupt occurs, the Program State of the running program is saved so that it can be
restarted from the same point after the interrupt has been handled.
Timer Interrupt

 What if a program has an infinite loop?

 We can add a time register, set to a specific value before a program stops, which is decremented with
each clock tick

 When the timer reaches zero, the Timer Interrupt bit (TI) is set to “1”, indicating that a timer interrupt
has occurred and transferring control to the interrupt handler

 Prevents a program from monopolizing the CPU


Interrupt Cycle
1. Suspend execution of current program
2. Save context
3. Set PC to start address of interrupt handler routine
4. Process interrupt
5. Restore context and continue interrupted program
Multiple interrupts

 Disable interrupts

 Processor will ignore further interrupts whilst processing one interrupt.


33 | P a g e
 They remain pending and are checked after first interrupt has been processed
Interrupts handled in sequence as they occur, however they can be prioritized:

 Low priority interrupts can be interrupted by higher priority interrupts

 When higher priority interrupt has been processed, processor returns to previous interrupt.
Context switch process
Steps:
1. Save the context of the processor, incl. PC and other registers.
2. Update the PCB of the currently running process. Includes changing the state of the process, other fields
and reason for changing the state.
3. Move the PCB of this process to the appropriate queue.
4. Select another process for execution.
5. Update the PCB of the process selected, incl. changing the state of this process to running.
6. Update memory mgt data structures depends on how address translation is managed.
7. Restore the context of the processor to that which existed at the time the selected process was switched
out.
Execution of a new program from within the current program (with the return to the old
program)
int system(const char *string) ;

34 | P a g e
Syntax
main()
{
int status ;
. . . .
status = system( “new_prog par1 par2”) ;
Analysis of status
. . . .
}
Shell process (starting your program in foreground)

Shell process (starting your program in foreground)

Process operations (System Calls)


They are:

 Process creation :(fork(),

 Process Execution : exec(),

 Process wait (Blocked) : wait()

 Process Termination : exit ()

35 | P a g e
Fork()

 A process is created using fork() system call.

 This call makes an exact replica of process state except for PID.

 The forked process is the “child” while the creator of the process is the parent.

 UNIX implements through the fork() and exec() system calls an elegant two-step mechanism for
process creation and execution.

 fork() is used to create the image of a process using the one of an existing one.

 exec is used to execute a program by overwriting that image with the program's one.
Process creation
 Once a parent creates a child process, a number of execution possibilities exist:
o The parent may immediately enter a wait state for the child to finish.
o The parent could immediately terminate;
o Both may continue to execute.
If the parent happens to terminate before the child has returned its value, then the child will
 become a zombie process and may be listed as such in the process status list!
The init process(pid = 1) is the parent of all processes.it is responsible for bringing up a
 Unix system after the kernel has been bootstrapped.
Initially, init duplicates (forks) several times and each child process replaces its code
 (execs) with the code of the program they are running.
All orphaned child processes becomes a child of init when the parent process dies.

Example
A call to fork() of the form:
#include <sys/types.h>
pid_t childpid;

36 | P a g e
...
childpid = fork(); /* returns child's pid in the parent, 0 in
the child */
...
On creating new process:
 The two processes obviously have two different process ids(pid).
 In a C program process ids are conveniently represented by variables of pid_t type, The type being
defined in the sys/types.h header.
 In UNIX the PCB of a process contains the id of the process's parent, - as parent id (ppid) the pid of
the process that called fork(),
 Child process id is: pid.

Example 2:simpfork.c
main()
{
int i;
printf("simpfork: pid = %d\n", getpid());
i = fork();
printf("Did a fork. It returned %d. getpid = %d. getppid
= %d\n", i, getpid(), getppid());
}

When it is run, the following happens:

 UNIX> simpfork
simpfork: pid = 914 Did a fork. It returned 915. getpid = 914. getppid = 381
Did a fork. It returned 0. getpid = 915. getppid = 914

 UNIX>

37 | P a g e
 When simpfork is executed, it has a pid of 914. Next it calls fork() creating a duplicate process with a
pid of 915. The parent gains control of the CPU, and returns from fork() with a return value of the
915 -- this is the child's pid. It prints out this return value, its own pid, and the pid of csh, which is
still 381. Then it exits. Next, the child gets the CPU and returns from fork() with a value of 0. It
prints out that value, its pid, and the pid of the parent.
getpid() and getppid()

 In order to know the pid of the child system call named getpid() is provided for this purpose,
andanother one, named getppid() is used to ask the system about the parent's id.

 Both functions take no arguments and return the requested value in pid_t type, or -1 in case of failure.

wait() system call

 UNIX defines several sophisticated inter-process communication (IPC) mechanisms, the simplest of
which is a parent's ability to test the termination status of its children.

 A synchronization mechanism is provided via the wait() system call, that allows a parent to sleep
until one of its children exits, and then get its exit status.

38 | P a g e
 When wait() is called, the process is suspended until one of its child processes exits, and then the call
returns with the exit status of the child process.
State diagram of unix process

Process termination

 Once a process executes its final instruction, a call to exit() is made.

 Operating system then flushes any I/O buffers.


All resources such as physical and virtual memory, I/O buffers, and open files are de-located and returned to
the operating system.

 A parent may terminate execution of children processes by calling abort().


Example : exit()

39 | P a g e
Note: since wait() returns the exit status multiplied by 256 (contained in the upper 8 bits), the status
value is shifted right 8 bits (divided by 256) to obtain the correct value.
Example 2; Process system call- execlp( )
/* myshell.c
This program is a simple command interpreter that uses execlp() to
execute commands typed in by the user.
*/
#include <stdio.h>
#define EVER ;;
int main()
{
int process;
char line[81];
for (EVER)
{
fprintf(stderr, "cmd: ");
if ( gets (line) == (char *) NULL) /* blank line
input */
exit (0);
/* create a new process */

40 | P a g e
process = fork ();
if (process > 0) /* parent */
wait((int *) 0); /* null pointer - return value not
saved */
else if (process == 0) /* child */
{ /* execute program */
execlp (line, line, (char *) NULL);
/* some problem if exec returns */
fprintf (stderr, "Can't execute %s\n", line);
exit (1);
}
else if ( process == -1) /* can't create a new process */
{
fprintf (stderr, "Can't fork!\n");
exit (2);
}
}
}

Inter-Process Communication
Mechanisms for IPC
Two basic IPC mechanism:

 Shared memory

 Message passing
Shared memory requires that these processes share a common buffer pool.
The code for implementing the buffer can be written explicitly by the application programmer.
Another way to achieve the same effect is for the operating system to provide the means for cooperating
processes to communicate with each other via an inter process communication
(IPC) facility.
IPC provides a mechanism to allow processes to communicate and to synchronize their actions without
sharing the same address space.

41 | P a g e
IPC is particularly useful in a distributed environment where the communicating processes may reside on
different computers connected with a network. An example is a chat program used on the World Wide Web.
Shared Memory

 Shared memory offers an extremely fast way of communicating; any data written by one process to a
shared memory region can be read immediately by any other process that has mapped that region
into its address space.

 To obtain synchronization, however, shared memory must be used in conjunction with another

Inter process-communication mechanism


Steps in creating and using a shared memory

 One of the processes creates a shared segment. Other processes get ID of the created segment.

 Each process, using the same key, attaches to itself the created shared segment.

 Now each process may write and read data into the shared segment.

 To avoid possible race condition, processes should coordinate using shared memory.

 Each process detaches the segment (after finishing).

Normally, UNIX prevents a user process from accessing any data in memory belonging to another process.

System calls for shared memory -shmget()


 shmget()- creates a shm segment

 Creating a shared segment or getting its ID

42 | P a g e

 The key argument is an access value associated with the semaphore ID.
 The size argument is the size in bytes of the requested shared memory.
 The flag 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).

43 | P a g e
System calls for Attaching to shared memory - Shmat()
 Suppose process 1, a server, uses shmget() to request a shared memory segment successfully. That
shared memory segment exists somewhere in the memory, but is not yet part of the address space of
process 1 (shown with dashed line below).

Similarly, if process 2 requests the same shared memory segment with the same key value, process 2 will be
granted the right to use the shared memory segment; but it is not yet part of the address space of process 2.
To make a requested shared memory segment part of the address space of a process, use shmat().

Attaching (mapping) the existing memory segment (getting its pointer).

 shmat() returns a pointer address, to the head of the shared segment associated with a valid shared
memory id from shmget().
 shmdt() detaches the shared memory segment located at the address indicated by addr shmdt ( ptr ) ;
Where ptr- is result of shmat()
Features of shared memory
 Efficiency (no intermediate copying of data as in pipes)
44 | P a g e
 Random access (a sequential byte stream in pipes)
 Many-to-many mechanism of IPC: many processes may attach the same segment (pipes provide
one-to-one mechanism of IPC)
 No synchronization is provided (pipes provide a synchronization) – Disadvantage.
 NB: Pipes are used extensively in message passing

Process A Process B

#include … #include …
#define MSIZ 27 #define MSIZ 27
main() main()
{ char c ; int shmid ; { char c ; int shmid ;
key_t key = 123 ; key_t key = 123 ;
char *shm, *s ; char *shm, *s ;
if ( (shmid = shmget( key,MSIZ,IPC_CREAT | 0666) ) < 0 ) if ( (shmid = shmget( key,0) ) < 0 )
{error…; exit(1) ; }
if ( (shm = shmat( shmid, NULL, 0)) == (char *) –1 )
(error … ; exit(1) ; } {error … ; exit(1) ; }
/*Put data into shared memory */
s = shm ; if ( (shm = shmat( shmid, NULL, 0)) == (char *) –1 )
for (c = „a‟ ; c <= „z‟ ; c++ ) (error … ; exit(1) ; }
*s++ = c ; /* get from shared memory */
*s = „\0‟ ; for (s=shm ; *s != „\0‟ ; s++ )
/*wait until process B changes the first character */ putchar( *s ) ; / * to display */
putchar( „\n‟) ;
while(*shm != „*‟ ) sleep( 1 ); /* Change the first char in segment */
shmdt( shm ) ; *shm = „*‟ ;
exit( 0 ) ; shmdt ( shm ) ; /* detach */
} exit( 0 ) ;
}

File 11_5.c File 11_6.c

45 | P a g e
Message Passing IPC
 The function of a message system is to allow processes to communicate with one another without the
need to resort to shared data. An IPC facility provides at least the two operations:
 send( dest, &message)
 receive( source, &message).
 If processes P and Q want to communicate, they must send messages to and receive messages from
each other; a communication link must exist between them.

Local IPC
- takes place in the same machine.

46 | P a g e
Remote IPC
-Takes place in the different machines.

Host 1 Host 2
Client
Process A Process B
Server

OS kernel OS kernel
request

Network

reply

Mechanisms for IPC


Mechanisms of IPC
in UNIX

For processes on For processes on


the same host separate hosts

For data For Network


exchange synchronization mechanisms

semaphores
Remote
signals procedure call
(RPC)
pipes
message queues Transport Layer
Interface (TLI)
shared memory
sockets
files

47 | P a g e
Process Synchronization
 Since processes frequently needs to communicate with other processes therefore, there is a need for a
well Structured communication, in order to avoid synchronization problems such as Race Condition
(shared memory)
 In operating systems, processes that are working together share some common storage (main
memory, file etc.) that each process can read and write. When two or more processes are reading or
writing some shared data and the final result depends on who runs precisely when, are called race
conditions.
 A race condition is a flaw in a process whereby the output and/or result of the process is
unexpectedly and critically dependent on the sequence or timing of other events.
 Concurrently executing threads that share data need to synchronize their operations and processing in
order to avoid race condition on shared data. Only one „customer‟ thread at a time should be allowed
to examine and update the shared variable.

Race Conditions
Race conditions are also possible in Operating Systems. If the ready queue is implemented as a linked list
and if the ready queue is being manipulated during the handling of an interrupt, then interrupts must be
disabled to prevent another interrupt before the first one completes. If interrupts are not disabled than the
linked list could become corrupt.

Critical section problem


The critical section of a program is a fragment, which performs the access to a shared resource (such as a
common variable).
No two processes should enter their critical section at the same time, this causes what is called race
condition. A race condition occurs when multiple processes access and manipulate the same data
concurrently, and the outcome of the execution depends on the particular order in which the access takes
place.
To avoid this condition we need some form of synchronization .

48 | P a g e
 The key to preventing trouble involving shared memory is find some way to prohibit more than one
process from reading and writing the shared data simultaneously. That part of the program where the
shared memory is accessed is called the Critical Section. To avoid race conditions and flawed results,
one must identify codes in Critical Sections in each thread.
 The characteristic properties of the code that form a Critical Section are Codes that reference one or
more variables in a “read-update-write” fashion while any of those variables is possibly being altered
by another thread.
 Codes that alter one or more variables that are possibly being referenced in “read-updatewrite”
fashion by another thread. Codes use a data structure while any part of it is possibly being altered by
another thread.
 Codes alter any part of a data structure while it is possibly in use by another thread.
 Here, the important point is that when one process is executing shared modifiable data in its critical
section, no other process is to be allowed to execute in its critical section. Thus, the execution of
critical sections by the processes is mutually exclusive in time.

Mutual Exclusion Conditions


If we could arrange matters such that no two processes were ever in their critical sections simultaneously, we
could avoid race conditions. We need four conditions to hold to have a good solution for the critical section
problem (mutual exclusion).
 No two processes may at the same moment inside their critical sections.
 No assumptions are made about relative speeds of processes or number of CPUs.
 No process should outside its critical section should block other processes.
 No process should wait arbitrary long to enter its critical section.

Semaphores
A semaphore is an integer variables that restricts access to shared resources. Main purpose is to synchronize
the access of processes to shared resources (files, shared memory), by enforcing mutual exclusion to the
resource.

49 | P a g e
Monitors
 A higher-level abstraction that provides a convenient and effective mechanism for process
Synchronization.
 Monitors are embedded in some concurrent programming languages. Java has monitors.
 Monitors enforce a style of programming where complex synchronization code doesn‟t get mixed
with other code: it is separated and put in monitors.

50 | P a g e
POSIX THREADS PROGRAMMING

Pthreads Overview
What is a Thread?
 A thread is defined as an independent stream of instructions that can be scheduled to run as such by
the operating system.
 To the software developer, the concept of a "procedure" that runs independently from its main

program may best describe a thread.


 To go one step further, imagine a main program (a.out) that contains a number of procedures. Then
imagine all of these procedures being able to be scheduled to run simultaneously and/or
independently by the operating system. That would describe a "multi-threaded" program.
 Before understanding a thread, one first needs to understand a UNIX process. A process is created by
the operating system, and requires a fair amount of "overhead". Processes contain information about
program resources and program execution state, including:
o Process ID, process group ID, user ID, and group ID
o Environment
o Working directory.
o Program instructions
o Registers
o Stack
o Heap
o File descriptors
o Signal actions
o Shared libraries
o Inter-process communication tools (such as message queues, pipes, semaphores, or
shared memory).

51 | P a g e
Figure: Unix process

Figure : Threads Within a Unix Process


52 | P a g e
 Threads use and exist within these process resources, yet are able to be scheduled by the operating
system and run as independent entities largely because they duplicate only the bare essential
resources that enable them to exist as executable code.
 This independent flow of control is accomplished because a thread maintains its own:
o Stack pointer
o Registers
o Scheduling properties (such as policy or priority)
o Set of pending and blocked signals
o Thread specific data.
So, in summary, in the UNIX environment a thread:

o Exists within a process and uses the process resources.


o Has its own independent flow of control as long as its parent process exists and the OS
supports it.
o Duplicates only the essential resources it needs to be independently schedulable
o May share the process resources with other threads that act equally independently(and
dependently)
o Dies if the parent process dies - or something similar
o Is "lightweight" because most of the overhead has already been accomplished through the
creation of its process.
 Because threads within the same process share resources:
o Changes made by one thread to shared system resources (such as closing a file) will be
seen by all other threads.
o Two pointers having the same value point to the same data.
o Reading and writing to the same memory locations is possible, and therefore requires
explicit synchronization by the programmer.

Pthreads Overview

What are Pthreads?


 Historically, hardware vendors have implemented their own proprietary versions of threads. These
implementations differed substantially from each other making it difficult for programmers to develop portable
threaded applications.

53 | P a g e
 In order to take full advantage of the capabilities provided by threads, a standardized programming interface
was required.

o For UNIX systems, this interface has been specified by the IEEE POSIX 1003.1c standard (1995).

o Implementations adhering to this standard are referred to as POSIX threads, or Pthreads.

o Most hardware vendors now offer Pthreads in addition to their proprietary API's.

 The POSIX standard has continued to evolve and undergo revisions, including the Pthreads specification.

 Pthreads are defined as a set of C language programming types and procedure calls, implemented with a
pthread.h header/include file and a thread library - though this library may be part of another library, such

as libc, in some implementations.

Why Pthreads?

 In the world of high performance computing, the primary motivation for using Pthreads is to realize potential
program performance gains.

 When compared to the cost of creating and managing a process, a thread can be created with much less
operating system overhead. Managing threads requires fewer system resources than managing processes.

 For example, the following table compares timing results for the fork() subroutine and the
pthread_create() subroutine. Timings reflect 50,000 process/thread creations, were performed with the

time utility, and units are in seconds, no optimization flags.

 Note: don't expect the sytem and user times to add up to real time, because these are SMP systems
with multiple CPUs working on the problem at the same time. At best, these are approximations run
on local machines, past and present.

fork() pthread_create()
Platform
real user sys real user sys

Intel 2.6 GHz Xeon E5-2670 (16 cores/node) 8.1 0.1 2.9 0.9 0.2 0.3

Intel 2.8 GHz Xeon 5660 (12 cores/node) 4.4 0.4 4.3 0.7 0.2 0.5

AMD 2.3 GHz Opteron (16 cores/node) 12.5 1.0 12.5 1.2 0.2 1.3

54 | P a g e
AMD 2.4 GHz Opteron (8 cores/node) 17.6 2.2 15.7 1.4 0.3 1.3

IBM 4.0 GHz POWER6 (8 cpus/node) 9.5 0.6 8.8 1.6 0.1 0.4

IBM 1.9 GHz POWER5 p5-575 (8 cpus/node) 64.2 30.7 27.6 1.7 0.6 1.1

IBM 1.5 GHz POWER4 (8 cpus/node) 104.5 48.6 47.2 2.1 1.0 1.5

INTEL 2.4 GHz Xeon (2 cpus/node) 54.9 1.5 20.8 1.6 0.7 0.9

INTEL 1.4 GHz Itanium2 (4 cpus/node) 54.5 1.1 22.2 2.0 1.2 0.6

 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.
 Threaded applications offer potential performance gains and practical advantages over non-threaded
applications in several other ways:

o 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.

o Priority/real-time scheduling: tasks which are more important can be scheduled to supersede
or interrupt lower priority tasks.

o Asynchronous event handling: tasks which service events of indeterminate frequency and
duration can be interleaved. For example, a web server can both transfer data from previous
requests and manage the arrival of new requests.

 The primary motivation for considering the use of Pthreads on an SMP architecture is to achieve
optimum performance. In particular, if an application is using MPI for on-node communications,
there is a potential that performance could be greatly improved by using Pthreads for on-node data
transfer instead.
 For example:

o MPI libraries usually implement on-node task communication via shared memory, which
involves at least one memory copy operation (process to process).

55 | P a g e
o For Pthreads there is no intermediate memory copy required because threads share the same
address space within a single process. There is no data transfer, per se. It becomes more of a
cache-to-CPU or memory-to-CPU bandwidth (worst case) situation. These speeds are much
higher.

Designing Threaded Programs

Parallel Programming:
 On modern, multi-cpu machines, pthreads are ideally suited for parallel programming, and whatever applies to
parallel programming in general, applies to parallel pthreads programs.

 There are many considerations for designing parallel programs, such as:

o What type of parallel programming model to use?

o Problem partitioning

o Load balancing

o Communications

o Data dependencies

o Synchronization and race conditions

o Memory issues

o I/O issues

o Program complexity

o Programmer effort/costs/time

 In general though, in order for a program to take advantage of Pthreads, it must be able to be organized into
discrete, independent tasks which can execute concurrently. For example, if routine1 and routine2 can be
interchanged, interleaved and/or overlapped in real time, they are candidates for threading.

56 | P a g e
 Programs having the following characteristics may be well suited for pthreads:

o Work that can be executed, or data that can be operated on, by multiple tasks simultaneously:

o Block for potentially long I/O waits

o Use many CPU cycles in some places but not others

o Must respond to asynchronous events

o Some work is more important than other work (priority interrupts)

 Several common models for threaded programs exist:

o Manager/worker: a single thread, the manager assigns work to other threads, the workers. Typically,
the manager handles all input and parcels out work to the other tasks. At least two forms of the
manager/worker model are common: static worker pool and dynamic worker pool.

o Pipeline: a task is broken into a series of suboperations, each of which is handled in series, but
concurrently, by a different thread. An automobile assembly line best describes this model.

o Peer: similar to the manager/worker model, but after the main thread creates other threads, it
participates in the work.

Shared Memory Model:

 All threads have access to the same global, shared memory

 Threads also have their own private data


57 | P a g e
 Programmers are responsible for synchronizing access (protecting) globally shared data.

Thread-safeness:

 Thread-safeness: in a nutshell, refers an application's ability to execute multiple threads simultaneously


without "clobbering" shared data or creating "race" conditions.

 For example, suppose that your application creates several threads, each of which makes a call to the same
library routine:

o This library routine accesses/modifies a global structure or location in memory.

o As each thread calls this routine it is possible that they may try to modify this global structure/memory
location at the same time.

o If the routine does not employ some sort of synchronization constructs to prevent data corruption, then
it is not thread-safe.
58 | P a g e
 The implication to users of external library routines is that if you aren't 100% certain the routine is thread-safe,
then you take your chances with problems that could arise.

 Recommendation: Be careful if your application uses libraries or other objects that don't explicitly guarantee
thread-safeness. When in doubt, assume that they are not thread-safe until proven otherwise. This can be done
by "serializing" the calls to the uncertain routine, etc.

Thread Limits:

 Although the Pthreads API is an ANSI/IEEE standard, implementations can, and usually do, vary in ways not
specified by the standard.

 Because of this, a program that runs fine on one platform, may fail or produce wrong results on another
platform.

 For example, the maximum number of threads permitted, and the default thread stack size are two important
limits to consider when designing your program.

 Several thread limits are discussed in more detail later in this tutorial.

59 | P a g e
The Pthreads API
 The original Pthreads API was defined in the ANSI/IEEE POSIX 1003.1 - 1995 standard. The POSIX standard
has continued to evolve and undergo revisions, including the Pthreads specification.

 Copies of the standard can be purchased from IEEE or downloaded for free from other sites online.

 The subroutines which comprise the Pthreads API can be informally grouped into four major groups:

1. Thread management: Routines that work directly on threads - creating, detaching, joining, etc. They
also include functions to set/query thread attributes (joinable, scheduling etc.)

2. Mutexes: Routines that deal with synchronization, called a "mutex", which is an abbreviation for
"mutual exclusion". Mutex functions provide for creating, destroying, locking and unlocking mutexes.
These are supplemented by mutex attribute functions that set or modify attributes associated with
mutexes.

3. Condition variables: Routines that address communications between threads that share a mutex.
Based upon programmer specified conditions. This group includes functions to create, destroy, wait
and signal based upon specified variable values. Functions to set/query condition variable attributes
are also included.

4. Synchronization: Routines that manage read/write locks and barriers.

 Naming conventions: All identifiers in the threads library begin with pthread_. Some examples are shown
below.

Routine Prefix Functional Group

pthread_ Threads themselves and miscellaneous subroutines

pthread_attr_ Thread attributes objects

pthread_mutex_ Mutexes

pthread_mutexattr_ Mutex attributes objects.

pthread_cond_ Condition variables

60 | P a g e
pthread_condattr_ Condition attributes objects

pthread_key_ Thread-specific data keys

pthread_rwlock_ Read/write locks

pthread_barrier_ Synchronization barriers

 The concept of opaque objects pervades the design of the API. The basic calls work to create or modify
opaque objects - the opaque objects can be modified by calls to attribute functions, which deal with opaque
attributes.

 The Pthreads API contains around 100 subroutines. This tutorial will focus on a subset of these - specifically,
those which are most likely to be immediately useful to the beginning Pthreads programmer.

 For portability, the pthread.h header file should be included in each source file using the Pthreads library.

 The current POSIX standard is defined only for the C language. Fortran programmers can use wrappers around
C function calls. Some Fortran compilers (like IBM AIX Fortran) may provide a Fortram pthreads API.

Compiling Threaded Programs

 Several examples of compile commands used for pthreads codes are listed in the table below.

Compiler / Platform Compiler Command Description

icc -pthread C
INTEL
Linux
icpc -pthread C++

pgcc -lpthread C
PGI
Linux
pgCC -lpthread C++

gcc -pthread GNU C


GNU
Linux, Blue Gene
g++ -pthread GNU C++

61 | P a g e
bgxlc_r / bgcc_r C (ANSI / non-ANSI)
IBM
Blue Gene
bgxlC_r, bgxlc++_r C++

Thread Management
Creating and Terminating Threads
Routines:
 pthread_create (thread,attr,start_routine,arg)

 pthread_exit (status)

 pthread_cancel (thread)

 pthread_attr_init (attr)

 pthread_attr_destroy (attr)

Creating Threads:
 Initially, your main() program comprises a single, default thread. All other threads must be explicitly created by
the programmer.

 pthread_create creates a new thread and makes it executable. This routine can be called any number of times
from anywhere within your code.

 pthread_create arguments:

o thread: An opaque, unique identifier for the new thread returned by the subroutine.

o attr: An opaque attribute object that may be used to set thread attributes. You can specify a thread
attributes object, or NULL for the default values.

o start_routine: the C routine that the thread will execute once it is created.

o arg: A single argument that may be passed to start_routine. It must be passed by reference as a pointer
cast of type void. NULL may be used if no argument is to be passed.

 The maximum number of threads that may be created by a process is implementation dependent. Programs
that attempt to exceed the limit can fail or produce wrong results.
62 | P a g e
 Querying and setting your implementation's thread limit - Linux example shown. Demonstrates querying the
default (soft) limits and then setting the maximum number of processes (including threads) to the hard limit.
Then verifying that the limit has been overridden.

 Once created, threads are peers, and may create other threads. There is no implied hierarchy or
dependency between threads.

Thread Attributes:
 By default, a thread is created with certain attributes. Some of these attributes can be changed by the
programmer via the thread attribute object.

 pthread_attr_init and pthread_attr_destroy are used to initialize/destroy the thread attribute


object.
 Other routines are then used to query/set specific attributes in the thread attribute object. Attributes
include:
o Detached or joinable state
o Scheduling inheritance
o Scheduling policy
o Scheduling parameters
o Scheduling contention scope
o Stack size
o Stack address
63 | P a g e
o Stack guard (overflow) size
 Some of these attributes will be discussed later.

Thread Binding and Scheduling:


 The Pthreads API provides several routines that may be used to specify how threads are scheduled for
execution.

 For example, threads can be scheduled to run FIFO (first-in first-out), RR (round-robin) or OTHER
(operating system determines). It also provides the ability to set a thread's scheduling priority value.

 The Pthreads API does not provide routines for binding threads to specific cpus/cores. However,
local implementations may include this functionality - such as providing the non-standard
pthread_setaffinity_np routine. Note that "_np" in the name stands for "non-portable".

 Also, the local operating system may provide a way to do this. For example, Linux provides the
sched_setaffinity routine.

Terminating Threads
 There are several ways in which a thread may be terminated:

o The thread returns normally from its starting routine. It's work is done.

o The thread makes a call to the pthread_exit subroutine - whether its work is done or not.

o The thread is canceled by another thread via the pthread_cancel routine.

o The entire process is terminated due to making a call to either the exec() or exit()

o If main() finishes first, without calling pthread_exit explicitly itself

 The pthread_exit() routine allows the programmer to specify an optional termination status parameter.
This optional parameter is typically returned to threads "joining" the terminated thread (covered
later).

 In subroutines that execute to completion normally, you can often dispense with calling pthread_exit() -
unless, of course, you want to pass the optional status code back.

64 | P a g e
 Cleanup: the pthread_exit() routine does not close files; any files opened inside the thread will remain
open after the thread is terminated.

 Discussion on calling pthread_exit() from main():

o There is a definite problem if main() finishes before the threads it spawned if you don't call
pthread_exit() explicitly. All of the threads it created will terminate because main() is done and

no longer exists to support the threads.

o By having main() explicitly call pthread_exit() as the last thing it does, main() will block and be
kept alive to support the threads it created until they are done.

Example: Pthread Creation and Termination


 This simple example code creates 5 threads with the pthread_create() routine. Each thread prints a
"Hello World!" message, and then terminates with a call to pthread_exit().

#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5

void *PrintHello(void *threadid)


{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}

int main (int argc, char *argv[])


{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}

/* Last thing that main() should do */


pthread_exit(NULL);
}

65 | P a g e
Output
In main: creating thread 0
In main: creating thread 1
Hello World! It's me, thread #0!
In main: creating thread 2
Hello World! It's me, thread #1!
Hello World! It's me, thread #2!
In main: creating thread 3
In main: creating thread 4
Hello World! It's me, thread #3!
Hello World! It's me, thread #4!

Passing Arguments to Threads


 The pthread_create() routine permits the programmer to pass one argument to the thread start routine. For cases
where multiple arguments must be passed, this limitation is easily overcome by creating a structure which
contains all of the arguments, and then passing a pointer to that structure in the pthread_create() routine.

 All arguments must be passed by reference and cast to (void *).

Example 1 - Thread Argument Passing


This code fragment demonstrates how to pass a simple integer to each thread. The calling thread uses
a unique data structure for each thread, insuring that each thread's argument remains intact
throughout the program.

/******************************************************************************
* FILE: hello_arg1.c
* DESCRIPTION:
* A "hello world" Pthreads program which demonstrates one safe way
* to pass arguments to threads during thread creation.
* AUTHOR: Blaise Barney
* LAST REVISED: 01/29/09
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 8

char *messages[NUM_THREADS];

void *PrintHello(void *threadid)


{
int *id_ptr, taskid;

sleep(1);
id_ptr = (int *) threadid;
66 | P a g e
taskid = *id_ptr;
printf("Thread %d: %s\n", taskid, messages[taskid]);
pthread_exit(NULL);
}

int main(int argc, char *argv[])


{
pthread_t threads[NUM_THREADS];
int *taskids[NUM_THREADS];
int rc, t;

messages[0] = "English: Hello World!";


messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";

for(t=0;t<NUM_THREADS;t++) {
taskids[t] = (int *) malloc(sizeof(int));
*taskids[t] = t;
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}

pthread_exit(NULL);
}

Example 2 - Thread Argument Passing


This example shows how to setup/pass multiple arguments via a structure. Each thread receives a
unique instance of the structure

/******************************************************************************
* FILE: hello_arg2.c
* DESCRIPTION:
* A "hello world" Pthreads program which demonstrates another safe way
* to pass arguments to threads during thread creation. In this case,
* a structure is used to pass multiple arguments.
* AUTHOR: Blaise Barney
* LAST REVISED: 01/29/09
******************************************************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 8

char *messages[NUM_THREADS];

67 | P a g e
struct thread_data
{
int thread_id;
int sum;
char *message;
};

struct thread_data thread_data_array[NUM_THREADS];

void *PrintHello(void *threadarg)


{
int taskid, sum;
char *hello_msg;
struct thread_data *my_data;

sleep(1);
my_data = (struct thread_data *) threadarg;
taskid = my_data->thread_id;
sum = my_data->sum;
hello_msg = my_data->message;
printf("Thread %d: %s Sum=%d\n", taskid, hello_msg, sum);
pthread_exit(NULL);
}

int main(int argc, char *argv[])


{
pthread_t threads[NUM_THREADS];
int *taskids[NUM_THREADS];
int rc, t, sum;

sum=0;
messages[0] = "English: Hello World!";
messages[1] = "French: Bonjour, le monde!";
messages[2] = "Spanish: Hola al mundo";
messages[3] = "Klingon: Nuq neH!";
messages[4] = "German: Guten Tag, Welt!";
messages[5] = "Russian: Zdravstvytye, mir!";
messages[6] = "Japan: Sekai e konnichiwa!";
messages[7] = "Latin: Orbis, te saluto!";

for(t=0;t<NUM_THREADS;t++) {
sum = sum + t;
thread_data_array[t].thread_id = t;
thread_data_array[t].sum = sum;
thread_data_array[t].message = messages[t];
printf("Creating thread %d\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)
&thread_data_array[t]);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}

Output
Creating thread 0
68 | P a g e
Creating thread 1
Creating thread 2
Creating thread 3
Creating thread 4
Creating thread 5
Creating thread 6
Creating thread 7
Thread 0: English: Hello World! Sum=0
Thread 1: French: Bonjour, le monde! Sum=1
Thread 2: Spanish: Hola al mundo Sum=3
Thread 3: Klingon: Nuq neH! Sum=6
Thread 4: German: Guten Tag, Welt! Sum=10
Thread 5: Russian: Zdravstvytye, mir! Sum=15
Thread 6: Japan: Sekai e konnichiwa! Sum=21
Thread 7: Latin: Orbis, te saluto! Sum=28

Joining and Detaching Threads

Routines:

 pthread_join (threadid,status)

 pthread_detach (threadid)

 pthread_attr_setdetachstate (attr,detachstate)

 pthread_attr_getdetachstate (attr,detachstate)

Joining:

 "Joining" is one way to accomplish synchronization between threads. For example:

69 | P a g e
 The pthread_join() subroutine blocks the calling thread until the specified threadid thread terminates.

 The programmer is able to obtain the target thread's termination return status if it was specified in the target
thread's call to pthread_exit().

 A joining thread can match one pthread_join() call. It is a logical error to attempt multiple joins on the same
thread.

 Two other synchronization methods, mutexes and condition variables, will be discussed later.

Joinable or Not?

 When a thread is created, one of its attributes defines whether it is joinable or detached. Only threads that are
created as joinable can be joined. If a thread is created as detached, it can never be joined.

 The final draft of the POSIX standard specifies that threads should be created as joinable.

 To explicitly create a thread as joinable or detached, the attr argument in the pthread_create() routine is used.
The typical 4 step process is:

1. Declare a pthread attribute variable of the pthread_attr_t data type

2. Initialize the attribute variable with pthread_attr_init()

3. Set the attribute detached status with pthread_attr_setdetachstate()

4. When done, free library resources used by the attribute with pthread_attr_destroy()

Detaching:

 The pthread_detach() routine can be used to explicitly detach a thread even though it was created as joinable.

 There is no converse routine.

Recommendations:

 If a thread requires joining, consider explicitly creating it as joinable. This provides portability as not all
implementations may create threads as joinable by default.

 If you know in advance that a thread will never need to join with another thread, consider creating it in a
detached state. Some system resources may be able to be freed.

70 | P a g e
Example: Pthread Joining

Example Code - Pthread Joining

This example demonstrates how to "wait" for thread completions by using the Pthread join routine. Since some
implementations of Pthreads may not create threads in a joinable state, the threads in this example are explicitly
created in a joinable state so that they can be joined later.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NUM_THREADS 4

void *BusyWork(void *t)


{
int i;
long tid;
double result=0.0;
tid = (long)t;
printf("Thread %ld starting...\n",tid);
for (i=0; i<1000000; i++)
{
result = result + sin(i) * tan(i);
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) t);
}

int main (int argc, char *argv[])


{
pthread_t thread[NUM_THREADS];
pthread_attr_t attr;
int rc;
long t;
void *status;

/* Initialize and set thread detached attribute */


pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

for(t=0; t<NUM_THREADS; t++) {


printf("Main: creating thread %ld\n", t);
rc = pthread_create(&thread[t], &attr, BusyWork, (void *)t);
if (rc) {
printf("ERROR; return code from pthread_create()
is %d\n", rc);
exit(-1);
}
}

71 | P a g e
/* Free attribute and wait for the other threads */
pthread_attr_destroy(&attr);
for(t=0; t<NUM_THREADS; t++) {
rc = pthread_join(thread[t], &status);
if (rc) {
printf("ERROR; return code from pthread_join()
is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status
of %ld\n",t,(long)status);
}

printf("Main: program completed. Exiting.\n");


pthread_exit(NULL);
}

Output
ain: creating thread 0
Main: creating thread 1
Thread 0 starting...
Main: creating thread 2
Thread 1 starting...
Main: creating thread 3
Thread 2 starting...
Thread 3 starting...
Thread 1 done. Result = -3.153838e+06
Thread 0 done. Result = -3.153838e+06
Main: completed join with thread 0 having a status of 0
Main: completed join with thread 1 having a status of 1
Thread 3 done. Result = -3.153838e+06
Thread 2 done. Result = -3.153838e+06
Main: completed join with thread 2 having a status of 2
Main: completed join with thread 3 having a status of 3
Main: program completed. Exiting.

Mutex Variables

Overview
 Mutex is an abbreviation for "mutual exclusion". Mutex variables are one of the primary means of
implementing thread synchronization and for protecting shared data when multiple writes occur.

 A mutex variable acts like a "lock" protecting access to a shared data resource. The basic concept of a
mutex as used in Pthreads is that only one thread can lock (or own) a mutex variable at any given
time. Thus, even if several threads try to lock a mutex only one thread will be successful. No other

72 | P a g e
thread can own that mutex until the owning thread unlocks that mutex. Threads must "take turns"
accessing protected data.

 Mutexes can be used to prevent "race" conditions. An example of a race condition involving a bank
transaction is shown below:

Thread 1 Thread 2 Balance

Read balance: $1000 $1000

Read balance: $1000 $1000

Deposit $200 $1000

Deposit $200 $1000

Update balance $1000+$200 $1200

Update balance $1000+$200 $1200

 In the above example, a mutex should be used to lock the "Balance" while a thread is using this
shared data resource.

 Very often the action performed by a thread owning a mutex is the updating of global variables. This
is a safe way to ensure that when several threads update the same variable, the final value is the same
as what it would be if only one thread performed the update. The variables being updated belong to a
"critical section".

 A typical sequence in the use of a mutex is as follows:

o Create and initialize a mutex variable

o Several threads attempt to lock the mutex

o Only one succeeds and that thread owns the mutex

73 | P a g e
o The owner thread performs some set of actions

o The owner unlocks the mutex

o Another thread acquires the mutex and repeats the process

o Finally the mutex is destroyed

 When several threads compete for a mutex, the losers block at that call - an unblocking call is
available with "trylock" instead of the "lock" call.

 When protecting shared data, it is the programmer's responsibility to make sure every thread that
needs to use a mutex does so. For example, if 4 threads are updating the same data, but only one uses
a mutex, the data can still be corrupted.

Creating and Destroying Mutexes


Routines:

 pthread_mutex_init (mutex,attr)

 pthread_mutex_destroy (mutex)

 pthread_mutexattr_init (attr)

 pthread_mutexattr_destroy (attr)

Usage:

 Mutex variables must be declared with type pthread_mutex_t, and must be initialized before they can
be used. There are two ways to initialize a mutex variable:

1. Statically, when it is declared. For example:


pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

2. Dynamically, with the pthread_mutex_init() routine. This method permits setting mutex
object attributes, attr.

74 | P a g e
The mutex is initially unlocked.

 The attr object is used to establish properties for the mutex object, and must be of type
pthread_mutexattr_t if used (may be specified as NULL to accept defaults). The Pthreads standard
defines three optional mutex attributes:

o Protocol: Specifies the protocol used to prevent priority inversions for a mutex.

o Prioceiling: Specifies the priority ceiling of a mutex.

o Process-shared: Specifies the process sharing of a mutex.

Note that not all implementations may provide the three optional mutex attributes.

 The pthread_mutexattr_init() and pthread_mutexattr_destroy() routines are used to create and destroy
mutex attribute objects respectively.

 pthread_mutex_destroy() should be used to free a mutex object which is no longer needed.

Locking and Unlocking Mutexes


Routines:

 pthread_mutex_lock (mutex)

 pthread_mutex_trylock (mutex)

 pthread_mutex_unlock (mutex)

Usage:
 The pthread_mutex_lock() routine is used by a thread to acquire a lock on the specified mutex variable. If the
mutex is already locked by another thread, this call will block the calling thread until the mutex is unlocked.

 pthread_mutex_trylock() will attempt to lock a mutex. However, if the mutex is already locked, the routine will
return immediately with a "busy" error code. This routine may be useful in preventing deadlock conditions, as
in a priority-inversion situation.

75 | P a g e
 pthread_mutex_unlock() will unlock a mutex if called by the owning thread. Calling this routine is required after
a thread has completed its use of protected data if other threads are to acquire the mutex for their work with the
protected data. An error will be returned if:

o If the mutex was already unlocked

o If the mutex is owned by another thread

 There is nothing "magical" about mutexes...in fact they are akin to a "gentlemen's agreement" between
participating threads. It is up to the code writer to insure that the necessary threads all make the the mutex lock
and unlock calls correctly. The following scenario demonstrates a logical error:

 Thread 1 Thread 2 Thread 3


 Lock Lock
 A = 2 A = A+1 A = A*B
 Unlock Unlock

Creative Question: When more than one thread is waiting for a locked mutex, which thread will be granted the lock
first after it is released?

Example: Using Mutexes


Example Code - Using Mutexes

This example program illustrates the use of mutex variables in a threads program that performs a
dot product. The main data is made available to all threads through a globally accessible structure.
Each thread works on a different part of the data. The main thread waits for all the threads to
complete their computations, and then it prints the resulting sum.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

/*
The following structure contains the necessary information
to allow the function "dotprod" to access its input data and
place its output into the structure.
*/

typedef struct
{
double *a;
double *b;

76 | P a g e
double sum;
int veclen;
} DOTDATA;

/* Define globally accessible variables and a mutex */

#define NUMTHRDS 4
#define VECLEN 100
DOTDATA dotstr;
pthread_t callThd[NUMTHRDS];
pthread_mutex_t mutexsum;

/*
The function dotprod is activated when the thread is created.
All input to this routine is obtained from a structure
of type DOTDATA and all output from this function is written into
this structure. The benefit of this approach is apparent for the
multi-threaded program: when a thread is created we pass a single
argument to the activated function - typically this argument
is a thread number. All the other information required by the
function is accessed from the globally accessible structure.
*/

void *dotprod(void *arg)


{

/* Define and use local variables for convenience */

int i, start, end, len ;


long offset;
double mysum, *x, *y;
offset = (long)arg;

len = dotstr.veclen;
start = offset*len;
end = start + len;
x = dotstr.a;
y = dotstr.b;

/*
Perform the dot product and assign result
to the appropriate variable in the structure.
*/

mysum = 0;
for (i=start; i<end ; i++)
{
mysum += (x[i] * y[i]);
}

/*
Lock a mutex prior to updating the value in the shared
structure, and unlock it upon updating.
*/
pthread_mutex_lock (&mutexsum);
dotstr.sum += mysum;

77 | P a g e
pthread_mutex_unlock (&mutexsum);

pthread_exit((void*) 0);
}

/*
The main program creates threads which do all the work and then
print out result upon completion. Before creating the threads,
the input data is created. Since all threads update a shared structure,
we need a mutex for mutual exclusion. The main thread needs to wait for
all threads to complete, it waits for each one of the threads. We specify
a thread attribute value that allow the main thread to join with the
threads it creates. Note also that we free up handles when they are
no longer needed.
*/

int main (int argc, char *argv[])


{
long i;
double *a, *b;
void *status;
pthread_attr_t attr;

/* Assign storage and initialize values */


a = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));
b = (double*) malloc (NUMTHRDS*VECLEN*sizeof(double));

for (i=0; i<VECLEN*NUMTHRDS; i++)


{
a[i]=1.0;
b[i]=a[i];
}

dotstr.veclen = VECLEN;
dotstr.a = a;
dotstr.b = b;
dotstr.sum=0;

pthread_mutex_init(&mutexsum, NULL);

/* Create threads to perform the dotproduct */


pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

for(i=0; i<NUMTHRDS; i++)


{
/*
Each thread works on a different set of data.
The offset is specified by 'i'. The size of
the data for each thread is indicated by VECLEN.
*/
pthread_create(&callThd[i], &attr, dotprod, (void *)i);
}

pthread_attr_destroy(&attr);

78 | P a g e
/* Wait on the other threads */
for(i=0; i<NUMTHRDS; i++)
{
pthread_join(callThd[i], &status);
}

/* After joining, print out the results and cleanup */


printf ("Sum = %f \n", dotstr.sum);
free (a);
free (b);
pthread_mutex_destroy(&mutexsum);
pthread_exit(NULL);
}

Condition Variables

Overview
 Condition variables provide yet another way for threads to synchronize. While mutexes implement
synchronization by controlling thread access to data, condition variables allow threads to synchronize based
upon the actual value of data.

 Without condition variables, the programmer would need to have threads continually polling (possibly in a
critical section), to check if the condition is met. This can be very resource consuming since the thread would
be continuously busy in this activity. A condition variable is a way to achieve the same goal without polling.

 A condition variable is always used in conjunction with a mutex lock.

 A representative sequence for using condition variables is shown below.

Main Thread

o Declare and initialize global data/variables which require synchronization (such as "count")

o Declare and initialize a condition variable object

o Declare and initialize an associated mutex

o Create threads A and B to do work

Thread A Thread B

 Do work up to the point where a certain o Do work


condition must occur (such as "count" must
reach a specified value) o Lock associated mutex

 Lock associated mutex and check value of a o Change the value of the global variable

79 | P a g e
global variable that Thread-A is waiting upon.

 Call pthread_cond_wait() to perform a o Check value of the global Thread-A wait


blocking wait for signal from Thread-B. variable. If it fulfills the desired condition, signal
Note that a call to pthread_cond_wait() Thread-A.
automatically and atomically unlocks the
associated mutex variable so that it can be o Unlock mutex.
used by Thread-B.
o Continue
 When signalled, wake up. Mutex is
automatically and atomically locked.

 Explicitly unlock mutex

 Continue

Main Thread

Join / Continue

Creating and Destroying Condition Variables


Routines:

 pthread_cond_init (condition,attr)

 pthread_cond_destroy (condition)

 pthread_condattr_init (attr)

 pthread_condattr_destroy (attr)

Usage:
 Condition variables must be declared with type pthread_cond_t, and must be initialized before they can be used.
There are two ways to initialize a condition variable:

1. Statically, when it is declared. For example:


pthread_cond_t myconvar = PTHREAD_COND_INITIALIZER;

2. Dynamically, with the pthread_cond_init() routine. The ID of the created condition variable is returned
to the calling thread through the condition parameter. This method permits setting condition variable
object attributes, attr.

80 | P a g e
 The optional attr object is used to set condition variable attributes. There is only one attribute defined for
condition variables: process-shared, which allows the condition variable to be seen by threads in other
processes. The attribute object, if used, must be of type pthread_condattr_t (may be specified as NULL to accept
defaults).

Note that not all implementations may provide the process-shared attribute.

 The pthread_condattr_init() and pthread_condattr_destroy() routines are used to create and destroy condition
variable attribute objects.

 pthread_cond_destroy() should be used to free a condition variable that is no longer needed.

Waiting and Signaling on Condition Variables


Routines:

 pthread_cond_wait (condition,mutex)

 pthread_cond_signal (condition)

 pthread_cond_broadcast (condition)

Usage:

 pthread_cond_wait() blocks the calling thread until the specified condition is signalled. This routine
should be called while mutex is locked, and it will automatically release the mutex while it waits.
After signal is received and thread is awakened, mutex will be automatically locked for use by the
thread. The programmer is then responsible for unlocking mutex when the thread is finished with it.

 The pthread_cond_signal() routine is used to signal (or wake up) another thread which is waiting on
the condition variable. It should be called after mutex is locked, and must unlock mutex in order for
pthread_cond_wait() routine to complete.

 The pthread_cond_broadcast() routine should be used instead of pthread_cond_signal() if more than


one thread is in a blocking wait state.

 It is a logical error to call pthread_cond_signal() before calling pthread_cond_wait().

Proper locking and unlocking of the associated mutex variable is essential when using these routines. For

81 | P a g e
example:

 Failing to lock the mutex before calling pthread_cond_wait() may cause it NOT to block.

 Failing to unlock the mutex after calling pthread_cond_signal() may not allow a matching
pthread_cond_wait() routine to complete (it will remain blocked).

Example: Using Condition Variables

Example Code - Using Condition Variables

This simple example code demonstrates the use of several Pthread condition variable routines. The
main routine creates three threads. Two of the threads perform work and update a "count" variable.
The third thread waits until the count variable reaches a specified value.

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_THREADS 3
#define TCOUNT 10
#define COUNT_LIMIT 12

int count = 0;
int thread_ids[3] = {0,1,2};
pthread_mutex_t count_mutex;
pthread_cond_t count_threshold_cv;

void *inc_count(void *t)


{
int i;
long my_id = (long)t;

for (i=0; i<TCOUNT; i++) {


pthread_mutex_lock(&count_mutex);
count++;

/*
Check the value of count and signal waiting thread when condition is
reached. Note that this occurs while mutex is locked.
*/
if (count == COUNT_LIMIT) {
pthread_cond_signal(&count_threshold_cv);
printf("inc_count(): thread %ld, count = %d Threshold reached.\n",
my_id, count);
}
printf("inc_count(): thread %ld, count = %d, unlocking mutex\n",

82 | P a g e
my_id, count);
pthread_mutex_unlock(&count_mutex);

/* Do some "work" so threads can alternate on mutex lock */


sleep(1);
}
pthread_exit(NULL);
}

void *watch_count(void *t)


{
long my_id = (long)t;

printf("Starting watch_count(): thread %ld\n", my_id);

/*
Lock mutex and wait for signal. Note that the pthread_cond_wait
routine will automatically and atomically unlock mutex while it waits.
Also, note that if COUNT_LIMIT is reached before this routine is run by
the waiting thread, the loop will be skipped to prevent pthread_cond_wait
from never returning.
*/
pthread_mutex_lock(&count_mutex);
while (count<COUNT_LIMIT) {
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %ld Condition signal received.\n", my_id);
count += 125;
printf("watch_count(): thread %ld count now = %d.\n", my_id, count);
}
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
}

int main (int argc, char *argv[])


{
int i, rc;
long t1=1, t2=2, t3=3;
pthread_t threads[3];
pthread_attr_t attr;

/* Initialize mutex and condition variable objects */


pthread_mutex_init(&count_mutex, NULL);
pthread_cond_init (&count_threshold_cv, NULL);

/* For portability, explicitly create threads in a joinable state */


pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
pthread_create(&threads[0], &attr, watch_count, (void *)t1);
pthread_create(&threads[1], &attr, inc_count, (void *)t2);
pthread_create(&threads[2], &attr, inc_count, (void *)t3);

/* Wait for all threads to complete */


for (i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
printf ("Main(): Waited on %d threads. Done.\n", NUM_THREADS);

83 | P a g e
/* Clean up and exit */
pthread_attr_destroy(&attr);
pthread_mutex_destroy(&count_mutex);
pthread_cond_destroy(&count_threshold_cv);
pthread_exit(NULL);

Output
Starting watch_count(): thread 1
inc_count(): thread 2, count = 1, unlocking mutex
inc_count(): thread 3, count = 2, unlocking mutex
watch_count(): thread 1 going into wait...
inc_count(): thread 3, count = 3, unlocking mutex
inc_count(): thread 2, count = 4, unlocking mutex
inc_count(): thread 3, count = 5, unlocking mutex
inc_count(): thread 2, count = 6, unlocking mutex
inc_count(): thread 3, count = 7, unlocking mutex
inc_count(): thread 2, count = 8, unlocking mutex
inc_count(): thread 3, count = 9, unlocking mutex
inc_count(): thread 2, count = 10, unlocking mutex
inc_count(): thread 3, count = 11, unlocking mutex
inc_count(): thread 2, count = 12 Threshold reached. Just sent signal.
inc_count(): thread 2, count = 12, unlocking mutex
watch_count(): thread 1 Condition signal received.
watch_count(): thread 1 count now = 137.
inc_count(): thread 3, count = 138, unlocking mutex
inc_count(): thread 2, count = 139, unlocking mutex
inc_count(): thread 3, count = 140, unlocking mutex
inc_count(): thread 2, count = 141, unlocking mutex
inc_count(): thread 3, count = 142, unlocking mutex
inc_count(): thread 2, count = 143, unlocking mutex
inc_count(): thread 3, count = 144, unlocking mutex
inc_count(): thread 2, count = 145, unlocking mutex
Main(): Waited on 3 threads. Final value of count = 145. Done

References
1. POSIX Standard: www.unix.org/version3/ieee_std.html
2. "Pthreads Programming". B. Nichols et al. O'Reilly and Associates.
3. "Threads Primer". B. Lewis and D. Berg. Prentice Hall
4. "Programming With POSIX Threads". D. Butenhof. Addison Wesley
5. www.awl.com/cseng/titles/0-201-63392-2
6. "Programming With Threads". S. Kleiman et al. Prentice Hall

84 | P a g e
SOCKET PROGRAMMING

Introduction to sockets
 A socket is a communications connection point (endpoint) that you can name and address in a
network. The processes that use a socket can reside on the same system or on different systems on
different networks. Sockets are useful for both stand-alone and network applications.

 Sockets commonly are used for client/server interaction. Typical system configuration places the
server on one machine, with the clients on other machines. The clients connect to the server,
exchange information, and then disconnect.

Socket characteristics:
Sockets share the following characteristics:

o A socket is represented by an integer. That integer is called a socket descriptor.

o A socket exists as long as the process maintains an open link to the socket.

o You can name a socket and use it to communicate with other sockets in a communication domain.

o Sockets perform the communication when the server accepts connections from them, or when it exchanges
messages with them.

o You can create sockets in pairs.

 Sockets are useful for both stand-alone and network applications. Sockets allow you to exchange
information between processes on the same machine or across a network, distribute work to the most
efficient machine, and allows access to centralized data easily.

 Socket application program interfaces (APIs) are the network standard for TCP/IP. A wide range of
operating systems support socket APIs. OS/400® sockets support multiple transport and networking
protocols. Socket system functions and the socket network functions are threadsafe.

 Socket programming shows how to use socket APIs to establish communication links between remote
and local processes. Programmers who use Integrated Language Environment® (ILE) C can use the

85 | P a g e
information to develop socket applications. You can also code to the sockets API from other ILE
languages, such as RPG.

 Socket application program interfaces (APIs) are the network standard for TCP/IP.
 A wide range of operating systems support socket APIs. – Ms Windows, Unix
 Socket system functions and the socket network functions are threadsafe.
 NB: The Java language also supports a socket programming interface.

Prerequisites for socket programming


1. Install QSYSINC library-This library provides necessary header files that are needed when compiling
socket applications.
2. Install the C licensed program.
3. Install TCP/IP and configure it for applications that use the AF_INET6 address family.

How sockets work


 Sockets are commonly used for client and server interaction.

 Typical system configuration places the server on one machine, with the clients on other machines.

 The clients connect to the server, exchange information, and then disconnect.

 A socket has a typical flow of events:

 In a connection-oriented client-to-server model, the socket on the server process waits for
requests from a client.

 To do this, the server first establishes (binds) an address that clients can use to find the server.

 When the address is established, the server waits for clients to request a service.

 The client-to-server data exchange takes place when a client connects to the server through a socket.

 The server performs the client's request and sends the reply back to the client.

86 | P a g e
Figure : A typical flow of events for connection-oriented socket session

 Typical flow of events for a connection-oriented socket:

1. The socket() API creates an endpoint for communications and returns a socket descriptor
that represents the endpoint.

2. Bind () - When an application has a socket descriptor, it can bind a unique name to the
socket. Servers must bind a name to be accessible from the network.

3. 3. The listen() API indicates a willingness to accept client connection requests.

4. The client application uses a connect() API on a stream socket to establish a connection to
the server.

5. The server application uses the accept() API to accept a client connection request.

6. Data Exchange -When a connection is established between stream sockets (between client
and server), then can use any of the socket API f data transfer.
87 | P a g e
7. Close() - When a server or client wants to stop operations, it issues a close() API to release
any system resources acquired by the socket.

Note: The socket APIs are located in the communications model between the application layer
and the transport layer of OSI model.

Socket characteristics
Sockets share some common characteristics:

1. A socket is represented by an integer. That integer is called a socket descriptor.

2. A socket exists as long as the process maintains an open link to the socket.

3. You can name a socket and use it to communicate with other sockets in a communication
domain.

4. Sockets perform the communication when the server accepts connections from them, or when
it exchanges messages with them.

5. You can create sockets in pairs (only for sockets in the AF_UNIX address family).

Types socket connections


 The connection that a socket provides can be :

1. connection-oriented or

2. connectionless

1. Connection-oriented communication

 Implies that a connection is established first, and a dialog between the programs follows.

 The server program establishes the available socket that is enabled to accept incoming connection
requests.

 Optionally, the server can assign a name to the service that it supplies, which allows clients to
identify where to obtain and how to connect to that service.

 The client program must request the service of the server program.

 The client request service by connecting to the distinct name or to the attributes associated with the
distinct name that the server program has designated- similar dialing a telephone number.

88 | P a g e
2. Connectionless communication

 No connection is established first, over which a dialog or data transfer can take place.

 Instead, the server program designates a name that identifies where to reach it (much like a post-
office box) - If you send a letter to a post office box, you cannot be absolutely sure that the receiver
got the letter. You might need to wait for a response to your letter.

 There is no active, real-time connection, in which data is exchanged.

Sockets and socket addresses

Sockets
 Sockets: abstract representation of a communication endpoint.

 work with Unix I/O services just like files, pipes & FIFOs.

 have special needs:

 establishing a connection

 specifying communication endpoint addresses

Socket address

 A protocol specific communication endpoint address that is or may be bound to a socket.

 { protocol, address-data }

 is the triple for TCP/IP protocol family:

 For example,

{tcp, 130.245.1.44, 23}

Associations

 An association is the 5-tuple that completely specifies the two end-points that comprise a connection:

{protocol, local-IP, local-port, remote-IP, remote-port}

e.g.:

{tcp, 130.245.1.44, 23, 130.245.1.45, 1024}

 A half-association specify one half of the connection.

89 | P a g e
E.g.
{tcp, 130.245.1.44, 23}
or
{tcp, 130.245.1.45, 1024}
synonyms: socket address , transport address.

Socket descriptors
 A data structure maintained by the operating system and stores state information about an object
instance, e.g.

o File

o Socket

 It is usually uniquely identified by an integer

Unix socket descriptor data structure

Socket creation & binding

Creating a Socket
Socket_desc=socket(int family,int type,int proto);
90 | P a g e
 family specifies the protocol family (PF_INET for TCP/IP).

 type specifies the type of service (SOCK_STREAM, SOCK_DGRAM).

 protocol specifies the specific protocol e.g IP(0 implies the default).

 Example:

s = socket(AF_INET , SOCK_STREAM , 0)

where 's' is the socket descriptor returned by the socket function

The socket()

o Returns a socket descriptor (small integer) or a -1 on error.

o Allocates resources needed for a communication endpoint - but it does not deal with endpoint addressing.

Binding a socket to a port - bind ()


 Like all services in a Network TCP/IP based, the sockets are always associated with a port, like
Telnet is associated to Port 23, FTP to 21.

 Bind() is used to specify for a socket the protocol port number where it will be waiting for messages.

 Question: which port could we bind to new service?

- Since the system pre-defined a lot of ports between 1 and 7000 ( /etc/services ) we choose the port
number 1500

Bind ( )

int bind( SOCKET sockfd, const struct sockaddr *myaddr, int addrlen);

 bind returns 0 if successful or -1 on error.

Assigning an address to a socket

 The bind() system call is used to assign an endpoint address to an existing socket.

 Bind parameters:

o socket descriptor: integer

o pointer to address: addr_struct *

91 | P a g e
o address length: integer

 Bind inserts the endpoint address information in the socket descriptor data structure.

 How to specify an address

o address structure depends on protocol family

Network connection establishment

Connection-oriented (e.g.TCP)

listen():(server)
– listen for incoming connection requests

• connect():(client)

– request connection to server

• accept():(server)

– accept an incoming connection request

• int listen( SOCKET sockfd, int backlog);

– sockfd: the TCP socket (already bound to an address)

– backlog: the number of incoming connections the kernel should be able to keep track of
(queue).

– listen() returns -1 on error (otherwise 0).

connect()
int connect(SOCKET sockfd, const struct sockaddr *server, socklen_t
addrlen);
92 | P a g e
sockfd: an already created TCP socket.

server: the address of the server (IP Address and TCP port number)

connect() returns 0 if OK, -1 on error

accept()
int accept( SOCKET sockfd, struct sockaddr* cliaddr, socklen_t
*addrlen);

sockfd: the passive mode TCP socket.

cliaddr: pointer to allocated space.

addrlen: a value-result argument

 must be set to the size of cliaddr

 on return, will be set to be the number of used bytes in cliaddr.

close()
int close( SOCKET sockfd);

 Either end of the connection can call the close() system call.

Examples:

/* client.c */

#include<sys/socket.h>

93 | P a g e
#include<sys/types.h>

#include<netinet/in.h>

#include<unistd.h>

#include<stdlib.h>

#include<stdio.h>

main(int argc,char *argv[])

int create_socket;

int bufsize = 1024;

char *buffer = malloc(bufsize);

struct sockaddr_in address;

printf("\x1B[2J");

if ((create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0)

printf("The Socket was created\n");

address.sin_family = AF_INET;

address.sin_port = htons(15000);

inet_pton(AF_INET,argv[1],&address.sin_addr);

if (connect(create_socket,(struct sockaddr
*)&address,sizeof(address)) == 0)

printf("The connection was accepted with the server


%s...\n",inet_ntoa(address.sin_addr));

do{

recv(create_socket,buffer,bufsize,0);

printf("Message recieved: %s\n",buffer);

if (strcmp(buffer,"/q"))

94 | P a g e
printf("Message to send: ");

gets(buffer);

send(create_socket,buffer,bufsize,0);

}while (strcmp(buffer,"/q"));

close(create_socket);

/* server.c */

#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<unistd.h>
#include<stdlib.h>
#include<stdio.h>

main()
{
int cont,create_socket,new_socket,addrlen;
int bufsize = 1024;
char *buffer = malloc(bufsize);
struct sockaddr_in address;

printf("\x1B[2J");
if ((create_socket = socket(AF_INET,SOCK_STREAM,0)) > 0)
printf("The socket was created\n");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(15000);
if (bind(create_socket,(struct sockaddr *)&address,sizeof(address)) == 0)
printf("Binding Socket\n");
listen(create_socket,3);
addrlen = sizeof(struct sockaddr_in);
new_socket = accept(create_socket,(struct sockaddr *)&address,&addrlen);
if (new_socket > 0){
printf("The Client %s is connected...\n",inet_ntoa(address.sin_addr));
for(cont=1;cont<5000;cont++)
printf("\x7");
}
do{
printf("Message to send: ");
gets(buffer);

95 | P a g e
send(new_socket,buffer,bufsize,0);
recv(new_socket,buffer,bufsize,0);
printf("Message recieved: %s\n",buffer);
}while(strcmp(buffer,"/q")); //user „q‟ to quit
close(new_socket);
close(create_socket);
}

How to compile and Run socket program


 To compile client.c use:

o gcc -g client.c -o client

o It generates an executable file client.exe

 To run the client use:

o ./client

 To run the program with server IP address or name as an argument, use IP address.

E.g ./client 203.106.93.94

 Make sure your previous server program is running.

 You can try running the server and client program at different machines.

References
1. UNIX Network Programming Volume 1, 2nd Edition

2. Stevens - Unix Network Programming - Vol. I - The Sockets Networking API 3e (2003).

3. Unix Network Programming - Volume I - The Sockets Networking API%2C 3rd Edition

SAMPLE EXAMINATIONS

96 | P a g e
UNIVERSITY EXAMINATION
SCHOOL OF APPLIED AND SOCIAL SCIENCES

DEPARTMENT OF INFORMATION TECHNOLOGY

EXAMINATION FOR BACHELOR OF BUSINESS INFORMATION TECHNOLOGY

COURSE CODE: BIT 4206

COURSE TITLE: NETWORK PROGRAMMING

TIME: 2HRS

INSTRUCTIONS

Answer Question One And Any Other Two

Question One (30 marks) compulsory

(a) Define the following terms: [5marks]


(i). System program
(ii). Kernel
(iii). Shell
(iv). Device Manager
(v). System call
(b) Describe five roles of kernel in operating systems. [5marks]
(c) Write the system call syntax for performing the following operations;
(i). Create a new file

97 | P a g e
(ii). Open a file [3marks]
(iii). Creating a shared memory segment [3marks]
(iv). Creating a socket [3marks]
(d) Using illustration, explain the layered structure of Unix operating system. [6marks]

(e) With the help syntax expression, explain two basic operations of message passing. [5marks]
Question 2 (20marks)

(a) Using example describe the components of typical UNIX shell session. [6marks]
(b) Using examples differentiate between library and system calls. [4marks]
(c) Using example, write code segments for : [9marks]
i. Creating a new socket
ii. Binding newly created socket
iii. Accept incoming requests
(d) Explain one disadvantage of message passing system in comparison with shared memory segment.
[1marks]

Question 3 (20marks)

(a) Define a thread. [2marks]


(b) Explain three advantages of threads over process. [6marks]
(c) Pthreads API subroutines can be grouped into grouped into four major groups. State and discuss.
[8marks]

(d) Write the syntax code for the following Pthread operation, explaining its elements.[4marks]
(i). Creating new thread
(ii).Terminating a thread

Question 4 (20marks)

(a) Define socket. [2marks]


(b) Using diagram, explain the structure of remote based IPC system. [6marks]
(c) Discuss three types of socket interfaces offered by message passing systems [6marks]
(d) Define a process control block. [2marks]
(e) Differentiate between interrupt and trap. [4marks]

Question 5 (20marks)

98 | P a g e
(a) What is the system call used to detach a process from the shared memory segment once it no longer needs it. Write its
syntax. [3marks]
(b) Briefly explain how mutex variable works in thread management. [4marks]
(c) With the help of illustrative diagram, explain how server and client interacts using socket in a connection oriented
environment. Clearly show the flow of events. [8marks]
(d) Write a code to demonstrate the structure of Socket address. Explain its components. [5marks]

99 | P a g e

You might also like