Page 1
1Computer Science 213© 2006 Donald Acton
Layering Yet Again!Layering Yet Again!
Application programs
Operating system
Hardware
General Layering
Structure
Application
Transport
Network
Link
Network
Layering
Application
Unix I/O
File System
Disk Drive
File System
Layering
Page 2
2Computer Science 213© 2006 Donald Acton
On to protocolsOn to protocols
• We just finished file systems and explored what happened from the disk to the application
• A layered approach was used to organize things
• We are going to start at the application layer and explore computer protocols
Page 3
3Computer Science 213© 2006 Donald Acton
Communication Between Processes
Communication Between Processes
• When talking about shells the concept of pipes was introduced
grep "ok:" inputfile | sort | less
• This is really just one process sending data to another. It is a form of Interprocess Communication (IPC).
Page 4
4Computer Science 213© 2006 Donald Acton
Local IPCLocal IPC
Process1
Process2
Pipe
Page 5
5Computer Science 213© 2006 Donald Acton
Remote IPCRemote IPC
Process1
Process2
Pipe
Page 6
6Computer Science 213© 2006 Donald Acton
What Problems Does this Present?
What Problems Does this Present?
Process1
Process2
Page 7
7Computer Science 213© 2006 Donald Acton
Problem SummaryProblem Summary
• Initiator needs– something to write
to– to identify the
recipient– to define the
“language” of the data exchange
– a mechanism to make the call
• Receiver needs– something to read
from– to define the
“language” of the data exchange
– a mechanism to accept a call
– “caller ID” (sort of)
Page 8
8Computer Science 213© 2006 Donald Acton
IPC StagesIPC Stages
A communication between processes can be decomposed into 3 stages:
1. Establishing the connection between the callee and caller
2. Transferring of data3. Disconnecting (closing) the connection
The collection of calls involved in the above phases is the Socket API
Page 9
9Computer Science 213© 2006 Donald Acton
Identifying the CalleeIdentifying the Callee
• Must identify the machine being called– DNS Name (www.cs.ubc.ca) is the human
readable form– Gets translated to an IP address
(142.103.6.5, 127.0.0.1)
• Must identify the recipient on the machine– Port number – Port 80 (www-http), 194 (irc)
Page 10
10Computer Science 213© 2006 Donald Acton
Internet ConnectionsInternet Connections
Connection socket pair(128.2.194.242 :51213, 208.216.181.15:80)
Receiver(port 80)
Sender
Sender socket address128.2.194.242:51213
Receiver socket address208.216.181.15:80
Sender host address128.2.194.242
Receiver host address208.216.181.15
Adapted from: Computer Systems: A Programmer’s Perspective
Page 11
11Computer Science 213© 2006 Donald Acton
Establishing the Connection (1)Establishing the Connection (1)
• Caller– Creating the
“endpoint”
int fd;
fd = socket(PF_INET,SOCK_STREAM,0);
Page 12
12Computer Science 213© 2006 Donald Acton
Establishing the Connection (2)Establishing the Connection (2)
• Caller– Getting ready to make the call
struct sockaddr_in remoteAddr;unsigned long remoteIP = htonl(0xAB112090);
memset(&remoteAddr, 0, sizeof(remoteAddr));remoteAddr.sin_family = PF_INET;memcpy(&remoteAddr.sin_addr.s_addr, &remoteIP, sizeof(remoteIP));remoteAddr.sin_port = htons(7891);
Page 13
13Computer Science 213© 2006 Donald Acton
Establishing the Connection (3)Establishing the Connection (3)
• Caller– Making the actual call
connect(fd, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr));
• Ready to transmit/receive data when the call returns
Page 14
14Computer Science 213© 2006 Donald Acton
CalleeCallee
Caller1. Create a socket
2. Connect to
callee3. Transfer data4. Close
connection
Callee1. Create socket2. Specify contact
point (binding)3. Listen for calls4. Accept call5. Transfer data6. Close connection
Page 15
15Computer Science 213© 2006 Donald Acton
Establishing the Connection (1)Establishing the Connection (1)
Callee – struct sockaddr_in callerAddr; memset(&callerAddr,0,sizeof(callerAddr)); callerAddr.sin_family = PF_INET; callerAddr.sin_addr.s_addr =
htonl(INADDR_ANY);
callerAddr.sin_port = htons(7891); bind(fd, (struct sockaddr *) &callerAddr, sizeof(callerAddr))
Page 16
16Computer Science 213© 2006 Donald Acton
Purpose of BindPurpose of Bind
• Consider a machine with multiple network cards – Wireless and wired– Server on more than one network
Page 17
17Computer Science 213© 2006 Donald Acton
Establishing the Connection (2)Establishing the Connection (2)
• Callee – must tell the system it is ready to listen for connectionslisten(fd, 4)– fd – file descriptor of socket to listen– 2nd argument is how many unanswered
calls to queue up (your call is important to us please stay on the line!)
Page 18
18Computer Science 213© 2006 Donald Acton
Establishing the Connection (3)Establishing the Connection (3)
• Callee needs to actually accept the call
struct sockaddr_in caller;int cl_len = sizeof(caller);int callerFD;callerFD = accept(fd, (struct sockaddr *)&caller, &cl_len);
Page 19
19Computer Science 213© 2006 Donald Acton
Setting up a ConnectionSetting up a Connection
listenfd(3)
Caller
1. Callee blocks in accept, waiting for connection request on listening descriptor listenfd.
clientfd
Callee
listenfd(3)
Caller
clientfd
Callee 2. Caller makes connection request bycalling and blocking in connect.
listenfd(3)
Caller
clientfd
Callee
3. Callee returns connfd from accept.Caller returns from connect. Connection is now established between clientfd
and connfd.
connectionrequest
connfd(4)
Adapted from: Computer Systems: A Programmer’s Perspective
Page 20
20Computer Science 213© 2006 Donald Acton
Who Called?Who Called?
• Callee can determine caller by examining 2nd parameter
unsigned long callerIP = ntohl(caller.sin_addr.s_addr);unsigned short = ntohs(caller.sin_port);
Page 21
21Computer Science 213© 2006 Donald Acton
DisconnectingDisconnecting
• Either caller or callee can terminate a connection with the close() system call
close(callerFD);
Page 22
22Computer Science 213© 2006 Donald Acton
Exchanging DataExchanging Data
• Once the connection is established caller and callee can both send and receive data– i.e. the connection is bi-directional– The data is not interpreted by the
sockets and it is just a series of bytes. – Calls to send and receive are:
•send()/write()•recv()/read()
Page 23
23Computer Science 213© 2006 Donald Acton
The CallerThe Caller#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <time.h>int main(){ int fd; fd = socket(PF_INET, SOCK_STREAM,
0);
struct sockaddr_in remoteAddr; unsigned long remoteIP = htonl(0x7F000001); memset(&remoteAddr, 0,
sizeof(remoteAddr));
remoteAddr.sin_family = PF_INET; memcpy(&remoteAddr.sin_addr.s_addr, &remoteIP, sizeof(remoteIP)); remoteAddr.sin_port = htons(7891);
if (connect(fd, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr)) < 0) {
perror("Connection failed"); } else { char *msg = "Hi there\n"; time_t ltime; char buff[256]; time(<ime); write(fd, <ime, sizeof(ltime)); write(fd, msg, 10); int amt; amt = read(fd, buff, 256); while( amt > 0) { printf("Buffer %s", buff); amt = read(fd, buff, 256); } }}
Page 24
24Computer Science 213© 2006 Donald Acton
Caller´ (1)Caller´ (1)
#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <time.h>int main(){ int fd; fd = socket(PF_INET, SOCK_STREAM, 0);
Page 25
25Computer Science 213© 2006 Donald Acton
Caller´ (2)Caller´ (2)
struct sockaddr_in remoteAddr;
unsigned long remoteIP = htonl(0x7F000001);
memset(&remoteAddr, 0, sizeof(remoteAddr));
Page 26
26Computer Science 213© 2006 Donald Acton
Caller´ (3)Caller´ (3)
remoteAddr.sin_family = PF_INET;
memcpy(&remoteAddr.sin_addr.s_addr, &remoteIP, sizeof(remoteIP));
remoteAddr.sin_port = htons(7891);
if (connect(fd, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr)) < 0) {
Page 27
27Computer Science 213© 2006 Donald Acton
Caller´ (4)Caller´ (4)
perror("Connection failed"); } else { char *msg = "Hi there\n"; time_t ltime; char buff[256]; time(<ime); write(fd, <ime, sizeof(ltime)); write(fd, msg, 10); int amt;
Page 28
28Computer Science 213© 2006 Donald Acton
Caller´Caller´
amt = read(fd, buff, 256);
while( amt > 0) {
printf("Buffer %s", buff);
amt = read(fd, buff, 256);
}
}
}
Page 29
29Computer Science 213© 2006 Donald Acton
CalleeCallee#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <time.h>int main(){ int fd; fd = socket(PF_INET, SOCK_STREAM, 0); struct sockaddr_in callerAddr; memset(&callerAddr, 0, sizeof(callerAddr)); callerAddr.sin_family = PF_INET; callerAddr.sin_addr.s_addr = htonl(INADDR_ANY); callerAddr.sin_port = htons(7891); bind(fd, (struct sockaddr *) &callerAddr,
sizeof(callerAddr)); listen(fd, 4); struct sockaddr_in caller;
while(1) { int cl_len = sizeof(caller); int callerFD; callerFD = accept(fd,
(struct sockaddr *)&caller, &cl_len);
char buff[256]; int amt; time_t rtime; recv(callerFD, &rtime, sizeof(time_t), 0); amt = recv(callerFD, buff, 256, 0); printf("%s", buff); struct hostent *hp; hp = gethostbyaddr((char *)
&caller.sin_addr.s_addr, sizeof(long), PF_INET);
amt = snprintf(buff,256, "Connection from %s (%x) %x at %s",
hp->h_name, ntohl(caller.sin_addr.s_addr), (long) ntohs(caller.sin_port), ctime(&rtime));
send(callerFD, buff, amt, 0); sleep(10); send(callerFD, "Bye\n", 5, 0); close(callerFD); }}
Page 30
30Computer Science 213© 2006 Donald Acton
Callee (1)Callee (1)
#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h>#include <time.h>int main(){ int fd;
fd = socket(PF_INET, SOCK_STREAM, 0);
Page 31
31Computer Science 213© 2006 Donald Acton
Callee (2)Callee (2)
struct sockaddr_in callerAddr;
memset(&callerAddr, 0, sizeof(callerAddr));
callerAddr.sin_family = PF_INET;
callerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
callerAddr.sin_port = htons(7891);
Page 32
32Computer Science 213© 2006 Donald Acton
Callee (3)Callee (3) bind(fd, (struct sockaddr *) &callerAddr, sizeof(callerAddr));
listen(fd, 4);
struct sockaddr_in caller;
while(1) {
int cl_len = sizeof(caller);
int callerFD
callerFD = accept(fd, (struct sockaddr *)&caller, &cl_len);
Page 33
33Computer Science 213© 2006 Donald Acton
Callee (4)Callee (4)
char buff[256];
int amt;
time_t rtime;
recv(callerFD, &rtime, sizeof(time_t), 0);
amt = recv(callerFD, buff, 256, 0);
printf("%s", buff);
Page 34
34Computer Science 213© 2006 Donald Acton
Callee (5) Callee (5)
struct hostent *hp; hp = gethostbyaddr((char *) &caller.sin_addr.s_addr, sizeof(long),PF_INET);
amt = snprintf(buff,256, "Connection from %s (%x) %x at %s",
hp->h_name, ntohl(caller.sin_addr.s_addr), (long) ntohs(caller.sin_port), ctime(&rtime));
Page 35
35Computer Science 213© 2006 Donald Acton
Callee (6)Callee (6)
send(callerFD, buff, amt, 0);
sleep(10);
send(callerFD, "Bye\n", 5,0);
close(callerFD);
}
}
Page 36
36Computer Science 213© 2006 Donald Acton
Typical Call ProgressTypical Call ProgressCaller Callee
socket socket
bind
listen
accept
close
read
writeread
connect
write
read
Connectionrequest
EOF
Await connectionrequest fromnext caller
Adapted from: Computer Systems: A Programmer’s Perspective
Page 37
37Computer Science 213© 2006 Donald Acton
BSD Socket API SummaryBSD Socket API Summary• socket() – creates the socket• connect() – initiate a connection• bind() – indicates the IP address to use• listen() – marks the socket to receive
connections• read()/recv() – reads data• write()/send() - writes data• close() – shuts down the connection
Page 38
38Computer Science 213© 2006 Donald Acton
Other Useful FunctionsOther Useful Functions
• inet_aton() – string to network address
• inet_ntoa() – network address to string
• gethostbyname() gethostbyaddr() given a host name or address look it up
Page 39
39Computer Science 213© 2006 Donald Acton
Client Server ModelClient Server Model
• When designing a network based application how can we decide what goes where?
• One approach is to divide the functionality into client and server components
Page 40
40Computer Science 213© 2006 Donald Acton
Client/ServerClient/Server
• Client – is a process that is requesting some sort of service
• Server – is a process that supplies a service
• A particular process can be both a client and server
Page 41
41Computer Science 213© 2006 Donald Acton
Changing RolesChanging Roles
Database
HTTP Server
Page 42
42Computer Science 213© 2006 Donald Acton
Request/ResponseRequest/Response
Clientprocess
Serverprocess
1. Client sends request
2. Server processes
request
3. Server sends response4. Client processesresponse
Resource
Adapted from: Computer Systems: A Programmer’s Perspective
Page 43
43Computer Science 213© 2006 Donald Acton
The Chat ProblemThe Chat Problem
• Consider the following application scenario– Two network connected computers – Want to implement “chat”– When each user types their typing
appears on the other screen– User’s do not have to take turns and can
type at any time
Page 44
44Computer Science 213© 2006 Donald Acton
The Application’s TaskThe Application’s Task• Each application has two things to do
it must:– Read input from the keyboard and send
it to the remote machine– Read input from the remote machine
and write it to the screen
Page 45
45Computer Science 213© 2006 Donald Acton
Start with what we knowStart with what we know
• Assume we have the network connection established
while(1) {
read from networkwrite to screenread from keyboardwrite to network
}
Page 46
46Computer Science 213© 2006 Donald Acton
Do it with Fork!Do it with Fork!
if (fork()) { // parent
read from network
write to screen
} else { //child
read from keyboard
write to network
}
Page 47
47Computer Science 213© 2006 Donald Acton
Fork()Fork()
Chat ChatSocket
Chat Chat
Page 48
48Computer Science 213© 2006 Donald Acton
That was easy!That was easy!
• But…..– The overhead of forking the process is
high especially if the child is short lived– Exchanging information between the
child and parent is difficult– It is difficult for the parent to track the
children for resource management issues
Page 49
49Computer Science 213© 2006 Donald Acton
HTTP Server ExampleHTTP Server Example
• Accepts connections• Client sends commands
– GET, POST, OPTIONS, HEAD, PUT, DELETE
• Commands are in plain text ASCII• Server parses the request and sends
back content• 99% of HTTP requests are GETs
Page 50
50Computer Science 213© 2006 Donald Acton
Niave HTTP serverNiave HTTP server
while (1) {
accept connection
perform http request
close connection
}
Page 51
51Computer Science 213© 2006 Donald Acton
Request TimelineRequest Timeline
Page 52
52Computer Science 213© 2006 Donald Acton
HTTP Server – fork()HTTP Server – fork()while (1) {accept connection
if (fork() == 0) { perform http request processing} else {
if (too many workers) { wait for worker
}}
Page 53
53Computer Science 213© 2006 Donald Acton
Observations about ServerObservations about Server
• We would like to control the number of processes created
• Each request is computationally light and has little state and is small
• Also, could we have a design that, if appropriate, doesn’t force the client to open a new connection for each request?
Page 54
54Computer Science 213© 2006 Donald Acton
Worker PoolWorker Pool
• How about a model where there are a bunch of workers
• One worker checks for a connection to see if data arrives
• On data arrival worker services request
• New worker starts waiting
Page 55
55Computer Science 213© 2006 Donald Acton
Worker Pool DemonstrationWorker Pool Demonstration
Page 56
56Computer Science 213© 2006 Donald Acton
Process ShortcomingsProcess Shortcomings
• Switching between processes (i.e. scheduling) is slow
• Sharing large amounts of data through pipes or sockets is difficult
Page 57
57Computer Science 213© 2006 Donald Acton
ThreadsThreads
• To get rid of some of the problems of processes we can use threads
• Threads– Are started by a process and stay within
that process– Execute independently of each other– Share the same memory space
Page 58
58Computer Science 213© 2006 Donald Acton
Threads and ProcessesThreads and Processes
Computer
Page 59
59Computer Science 213© 2006 Donald Acton
Thread StatesThread States
New
Ready
Blocked
DeadRunning
Page 60
60Computer Science 213© 2006 Donald Acton
Thread APIThread API
• Defined by POSIX.1c• The API defines > 60 functions!!!• Java Thread class is much smaller
and many of the methods are informational
Page 61
61Computer Science 213© 2006 Donald Acton
Most Useful Thread FunctionsMost Useful Thread Functions
• Creating a thread• Starting the thread• Waiting for a thread to terminate• Terminating a thread• To simplify the using of threads let’s
develop an encapsulation of the simplest thread functions
Page 62
62Computer Science 213© 2006 Donald Acton
Encapsulation StrategyEncapsulation Strategy
Recall that an object is:–A collection of data that captures the state of the object
–A collection of methods that operate on the state
Is there some way to emulate this in a language like C?
Page 63
63Computer Science 213© 2006 Donald Acton
Approach?Approach?
What C construct could be used to aggregate data?
structsWhat about methods?
functions
Page 64
64Computer Science 213© 2006 Donald Acton
OrganizationOrganization
Java• new
C• A function that
allocates and initializes the struct and returns a pointer to the struct
struct Point { float x; float y; };
void *newPoint() {
struct Point *pt;
if (pt = malloc(sizeof(struct Point))) {
pt->x = pt->y = 0;
}
return pt;
}
Page 65
65Computer Science 213© 2006 Donald Acton
Organization cont’dOrganization cont’d
Java• Method invocation
point.method()
C• Just call a function,
but make the first parameter be the “object”
void *pt;
pt = newPoint();
setPoint(pt, 3.4, 1.3);
Page 66
66Computer Science 213© 2006 Donald Acton
Encapsulation ExampleEncapsulation Example
struct Point { float x; float y; };
void *newPoint() {
struct Point *pt;
if (pt = malloc(sizeof(struct Point))) {
pt->x = pt->y = 0;
}
return pt;
}
void setPoint(void * obj, float x, float y) {
struct Point *pt = obj;
pt->x = x;
pt->y = y;
}
main() {
void *pt;
pt = newPoint();
setPoint(pt, 3.4, 1.3);
….
}
Page 67
67Computer Science 213© 2006 Donald Acton
Relationship Between Thread Encapsulation and pthread
Relationship Between Thread Encapsulation and pthread
pthread
A
pthread
B
pthread
C
Thread
A
Thread
B
Thread
C
Page 68
68Computer Science 213© 2006 Donald Acton
Needed FunctionalityNeeded Functionality• Creation
– int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine, void*), void *arg);
• Cancellation – int pthread_cancel( pthread_t target_thread);
Page 69
69Computer Science 213© 2006 Donald Acton
Functionality cont’dFunctionality cont’d
• Join– int pthread_join(pthread_t thread,
void **status);
• Detach– int pthread_detach( pthread_t thread);
Page 70
71Computer Science 213© 2006 Donald Acton
Thread StructThread Struct
struct Thread {
void *(*entry_pt)(void*);
void *arg;
pthread_t id; // the thread ID
};int pthread_create(pthread_t *thread,
const pthread_attr_t *attr, void *(*start_routine, void*), void *arg);
Page 71
72Computer Science 213© 2006 Donald Acton
Thread FunctionsThread Functions
void *createThread(void* (*func)(void*),
void *parm);
int runThread(void *vthread, pthread_attr_t *attr);
int cancelThread(void * vthread);
int joinThread(void * vthread, void **thread_return);
Page 72
73Computer Science 213© 2006 Donald Acton
Thread Functions cont’dThread Functions cont’d
int detachThread(void *vthread);
pthread_t getThreadID( void *vthread);
void* getThreadArg( void *vthread);
Page 73
78Computer Science 213© 2006 Donald Acton
createThreadcreateThread
void *createThread(void* (*func)(void*), void * parm) {
struct Thread *thread; thread = malloc(sizeof(struct Thread)); if (thread) { thread->entry_pt = func; thread->arg = parm; } return thread;}
Page 74
79Computer Science 213© 2006 Donald Acton
runThreadrunThreadint runThread(void *vthread, pthread_attr_t *attr) { struct Thread *thread = vthread; if (vthread) { return pthread_create(&thread->id, attr,
thread->entry_pt, thread->arg ); } return -10;}
int cancelThread(void * vthread){ struct Thread *thread = vthread; return pthread_cancel(thread->id);}
Page 75
80Computer Science 213© 2006 Donald Acton
joinThreadjoinThreadint joinThread(void * vthread, void **thread_return){ struct Thread *thread = vthread; return pthread_join(thread->id, thread_return);}
int detachThread(void *vthread) // reaps a thread{ struct Thread *thread = vthread; return pthread_detach(thread->id);}
Page 76
81Computer Science 213© 2006 Donald Acton
AccessorsAccessorspthread_t getThreadID(void *vthread){ struct Thread *thread = vthread; return thread->id;}
void* getThreadArg(void * vthread){ struct Thread *thread = vthread; return thread->arg;}
Page 77
85Computer Science 213© 2006 Donald Acton
Creating and Running a ThreadCreating and Running a Thread
void *sortAndPrint(void *array) { … }
void *t2;t2 = createThread(sortAndPrint, ar1);runThread(t2, NULL);detachThread(t2); // Only call after
// runcancelThread(t2);free(t2);
Page 78
86Computer Science 213© 2006 Donald Acton
JoiningJoining
• Threads can only execute as long as their containing process exists
• The main() body of a program is a thread
• If any thread either directly or indirectly calls exit() or _exit() the process will be terminated
Page 79
87Computer Science 213© 2006 Donald Acton
Joining cont’dJoining cont’d
• If all the process’s work is being done by threads started from main() then main must not return prematurely
• Any thread can wait for another thread with the pthread_join() call encapsulated by:
joinThread(t2, NULL);
Page 80
88Computer Science 213© 2006 Donald Acton
Example Sorting and Printing
Example Sorting and Printing
• Have a function that takes as an argument an array of integers, sorts, and then prints them
• main() – Creates 3 arrays of integers– Creates 3 threads – Starts all 3 threads “simultaneously”
Page 81
89Computer Science 213© 2006 Donald Acton
Sort and PrintSort and Printint cs213Compare(const void *a, const void *b) { return *(int *)a - *(int *)b;}
void *sortAndPrint(void *array) { int i; int *b; b = (int *) array; qsort(array, aSize, sizeof(int), cs213Compare); for (i=0; i<aSize; i++) { printf("%3d ", b[i]); fflush(stdout); } printf("\n"); return NULL;}
Page 82
90Computer Science 213© 2006 Donald Acton
Sort and PrintSort and Print
int main(int argc, char * argv[]){ int array1[aSize]; int array2[aSize]; int array3[aSize]; int i; srandom(time(NULL)); for (i = 0; i < aSize; i++) { array1[i] = random() % (aSize * 10); array2[i] = random() % (aSize * 10); array3[i] = random() % (aSize * 10); printf("%3d %3d %3d\n", array1[i], array2[i],
array3[i]); }
Page 83
91Computer Science 213© 2006 Donald Acton
Sort and PrintSort and Print printf("\n");
void *t1, *t2, *t3; t1 = createThread(sortAndPrint, array1); t2 = createThread(sortAndPrint, array2); t3 = createThread(sortAndPrint, array3);
runThread(t2, NULL); pthread_attr_t attr; pthread_attr_init(&attr); runThread(t3, &attr); runThread(t1, NULL);
joinThread(t1, NULL); joinThread(t2, NULL); joinThread(t3, NULL); return 0;}
Page 84
92Computer Science 213© 2006 Donald Acton
Compare FunctionCompare Function
int cs213Compare(const void *a, const void *b) {
return *(int *)a - *(int *)b;
}
Page 85
93Computer Science 213© 2006 Donald Acton
Sort and Print FunctionSort and Print Function
void *sortAndPrint(void *array) { int i; int *b; b = (int *) array; qsort(array, aSize, sizeof(int), cs213Compare); for (i=0; i<10; i++) { printf("%3d ", b[i]); fflush(stdout); } printf("\n"); }
Page 86
94Computer Science 213© 2006 Donald Acton
Filling the arraysFilling the arrays
srandom(time(NULL));
for (i = 0; i < aSize; i++) {
array1[i] = random() % (aSize * 10);
array2[i] = random() % (aSize * 10);
array3[i] = random() % (aSize * 10);
printf("%3d %3d %3d\n", array1[i], array2[i], array3[i]);
}
Page 87
95Computer Science 213© 2006 Donald Acton
Running the ThreadsRunning the Threadsvoid *t1, *t2, *t3;t1 = createThread(sortAndPrint, array1);t2 = createThread(sortAndPrint, array2);t3 = createThread(sortAndPrint, array3);
runThread(t2, NULL);pthread_attr_t attr; pthread_attr_init(&attr);runThread(t3, &attr); runThread(t1, NULL); joinThread(t1, NULL);joinThread(t2, NULL);joinThread(t3, NULL);
Page 88
96Computer Science 213© 2006 Donald Acton
Output 1Output 1 53 14 27 2 31 85
30 11 67
50 7 39
29 16 79
3 99 90
40 26 32
29 82 64
15 61 73
75 38 23
This is the output from main of the unsorted numbers
Page 89
97Computer Science 213© 2006 Donald Acton
Output 2Output 2
2 3 15 29 29 30 40 50 53 75 7 11 14 16 26 31 38 61 82 99
23 27 32 39 64 67 73 79 85 90
Page 90
98Computer Science 213© 2006 Donald Acton
Output 3Output 3
2 3 15 29 7 61 … 53 75 99
23 27 32 39 64 67 73 79 85 90
2 3 15 29 7 … 99 50 53 32 75 39
64 67 73 79 85 90
Page 91
99Computer Science 213© 2006 Donald Acton
What Happened?What Happened?
• Before one thread finished, its quantum expired and another thread was run
• The thread switched out hadn’t finished
• Exactly when the switch occurs is unpredictable; therefore the output is unpredictable
Page 92
100Computer Science 213© 2006 Donald Acton
But why?But why?
• What is being shared?– The file descriptor attached to stdout, in
this example it is the screen (window)– Each time the thread is given a time
quantum it writes to stdout– The threads are taking turns writing to
stdout, hence the mixed output
Page 93
101Computer Science 213© 2006 Donald Acton
Real life examplesReal life examples
• Can you think of some real life examples where there is some notion of sharing, how is it regulated?
Page 94
102Computer Science 213© 2006 Donald Acton
Semaphores, the Computer Equivalent
Semaphores, the Computer Equivalent
• Developed by Edsger Dijkstra to solve synchronization problem in concurrent programming environments
• A special global variable, s, that can only be manipulated by the operations P(s) (proberen) and V(s) (verhogen)
• Works for both processes and threads
Page 95
103Computer Science 213© 2006 Donald Acton
AtomicAtomic
Definition: A series of actions is said to be
atomic if the execution of the actions has the exact same result as if the actions had been performed sequentially without interruption.
Page 96
104Computer Science 213© 2006 Donald Acton
Semaphore SemanticsSemaphore Semantics
• V(s) [ s = s + 1]– Operation is performed atomically
• P(s) [while (s == 0) {wait}; s = s – 1]– The test for 0 and decrement are done
atomically– If s is 0 then the process waits until the
value of s is modified by a V operation
Page 97
105Computer Science 213© 2006 Donald Acton
Underlying Semaphore Implementation
Underlying Semaphore Implementation
We know– That an application can be interrupted
at any time– That the kernel can schedule a new
process to run– When executing in the kernel interrupts
are disabled therefore any series of instructions is atomic
Page 98
106Computer Science 213© 2006 Donald Acton
Semaphore APISemaphore API
• Part of POSIX 1003.1b• Supplies semaphores in various
formats• Upon creation the semaphore values
is normally set to 0, although other values are allowed
• You will work with the supplied Semaphore class
Page 99
107Computer Science 213© 2006 Donald Acton
Semaphore EncapsulationSemaphore Encapsulation
void P(sem_t *_sysSem);
void V(sem_t *_sysSem);
sem_t createSemaphore();void destroySemaphore(sem_t
**_sysSem);
Page 100
108Computer Science 213© 2006 Donald Acton
createSemaphore()createSemaphore()
sem_t *createSemaphore(int count) { sem_t *_sysSem = malloc(sizeof(sem_t)); if (_sysSem) { memset( _sysSem, 0, sizeof( sem_t ) ); if (sem_init(_sysSem, 0, count) != 0) { // perror("Getting semaphore failed"); free(_sysSem); _sysSem = NULL; } } return _sysSem;}
Page 101
109Computer Science 213© 2006 Donald Acton
destroySemaphore()destroySemaphore()
void destroySemaphore(sem_t **_sysSem ) { if (_sysSem && *_sysSem) { if (sem_destroy(*_sysSem) != 0) { perror("Semaphore Destr. failed"); } else { free(*_sysSem); *_sysSem = NULL;
}}
}
Page 102
110Computer Science 213© 2006 Donald Acton
P()P()
void P(sem_t * _sysSem) { // wait, lock if (sem_wait(_sysSem) != 0) {
perror("Semaphore P() blocking");
pthread_cancel(pthread_self());
for(;;) sleep(60000);
} }
Page 103
111Computer Science 213© 2006 Donald Acton
V()V()
void V(sem_t *_sysSem) { //signal, unlock
if (sem_post(_sysSem) != 0) {
perror("Sem V()blocking");
pthread_cancel(pthread_self());
for(;;) sleep(60000);
}
}
Page 104
112Computer Science 213© 2006 Donald Acton
V()P()
V()
Semaphores in ActionSemaphores in Action
P()
P() V()T1
T2
T3
Time
Page 105
113Computer Science 213© 2006 Donald Acton
Using P() and V() in Sort and Print ExampleUsing P() and V() in
Sort and Print Example• All threads must use the same
semaphore • Given the way we have put things
together a global variable for the semaphore will be needed
• Add code sem_t *s = createSemaphore(1);
before the definition of sortAndPrint()
Page 106
114Computer Science 213© 2006 Donald Acton
Where do P() and V() go?Where do P() and V() go?
void *sortAndPrint(void *array) { int i; int *b; b = (int *) array; qsort(array, aSize, sizeof(int), cs213Compare); for (i=0; i<10; i++) { printf("%3d ", b[i]); fflush(stdout); } printf("\n"); }
Page 107
115Computer Science 213© 2006 Donald Acton
Semaphores & BanksSemaphores & Banks
•Consider a banking system that has a method to transfer money from one account to another
•Uses semaphores to prevent multiple simultaneous transfers from updating the same account at once
Page 108
116Computer Science 213© 2006 Donald Acton
Solution 1Solution 1
void transfer(int amt, BankA *a1, BankA *a2){
P(s);
if (valid balance) {
Withdraw(a1, amt);
Deposit(a2, amt);
}
V(s);
}
Page 109
117Computer Science 213© 2006 Donald Acton
Problem with Solution 1Problem with Solution 1
• Withdraw and deposit methods could take a long time if they involve going to disk
• With a single global semaphore no other transfers can be done while waiting, even if the transfer involves completely different accounts
Page 110
118Computer Science 213© 2006 Donald Acton
Solution 2Solution 2
void transfer(int amt, BankA *a1, BankA *a2){
P(a1->s); P(a2->s); if (valid balance) {
Withdraw(a1, amt);Deposit(a2, amt);
}V(a2->s); V(a1->s);
}
Page 111
119Computer Science 213© 2006 Donald Acton
Does solution 2 work?Does solution 2 work?
transfer(100,a1,a2);
1. P(a1->s);
2. P(a2->s);
transfer(100,a2,a1);
1. P(a2->s);
2. P(a1->s);
At this point each thread/process is waiting for the other so no further progress, by either thread/process, can be made.
Page 112
120Computer Science 213© 2006 Donald Acton
DeadlockDeadlock
Definition:A deadlock occurs when two or more processes/threads cannot make computational progress because the processes/threads, either directly or indirectly, are waiting for a resource the other process/thread holds.
Page 113
121Computer Science 213© 2006 Donald Acton
Wait-for-graphWait-for-graph
– For each process draw a square– For each resource (semaphore) draw a circle– If a resource is held by a process draw an
arrow from the resource to the process – If a process is waiting for a resource draw
an arrow from the process to the resource
If a cycle exists then there is a deadlock in the system
Page 114
122Computer Science 213© 2006 Donald Acton
Bank – wait-for-graphBank – wait-for-graph
Page 115
123Computer Science 213© 2006 Donald Acton
Bank – wait-for-graphBank – wait-for-graph
T1 T2
a1.s
a2.s
Page 116
124Computer Science 213© 2006 Donald Acton
Deadlock DetectionDeadlock Detection
• Can be done by keeping wait-for-graph
• Keeping a wait-for-graph is expensive as each time a resource is acquired, released, or waited for, the graph must be updated
• Running the cycle detection algorithm can consume many resources if it is done too frequently
Page 117
125Computer Science 213© 2006 Donald Acton
So you found a deadlock, what should be done?
So you found a deadlock, what should be done?
• Something must be done otherwise the system will remain blocked
• Select one of the blocked process and return acquisition call failure
• Which process should be selected– Oldest?– One involved in the most cycles?– One involved in the least cycles?
Page 118
126Computer Science 213© 2006 Donald Acton
Other StrategiesOther Strategies
• Have a timeout associated with resource acquisition– Don’t have to do deadlock detection– May timeout when there isn’t a deadlock
• Put the onus on the designer to develop deadlock free algorithms
Page 119
127Computer Science 213© 2006 Donald Acton
Bank -> Deadlock FreeBank -> Deadlock Free
• All process agree to acquire resources in a specific order
Page 120
128Computer Science 213© 2006 Donald Acton
LivelockLivelock
• More difficult to deal with than deadlock
• Occurs when 2 or more processes change their state in response to each other
• State change has the appearance of doing work (unlike a deadlock) but no computational progress is being made
Page 121
129Computer Science 213© 2006 Donald Acton
Okay, where were we?Okay, where were we?
• Started this section out with http server
• Wanted threads to replace fork()• Can’t have an unlimited number of
threads so use a worker pool• Need semaphores to help with the
problem of sharing
Page 122
130Computer Science 213© 2006 Donald Acton
HTTP Server Again!HTTP Server Again!
while (1) {accept connection
if (fork() == 0) { perform http request processing} else {
if (too many workers) { wait for worker
}}
Page 123
131Computer Science 213© 2006 Donald Acton
Thread Design ModelThread Design Model
Master
threadBuffer
...
Accept
connections
Insert Request
descriptor Remove
Request
Worker
thread
Worker
thread
Client
Client
...
Service client
Service client
Pool of worker threads
Adapted from: Computer Systems: A Programmer’s Perspective
Server Machine
Page 124
132Computer Science 213© 2006 Donald Acton
HTTP Server MainHTTP Server Main
main() {setup Socket to listen oninitialize semaphoresstart pool of workerswhile (1) {
accept new connectionprepare requestput request in queue
}
Page 125
133Computer Science 213© 2006 Donald Acton
Worker ThreadWorker Thread
void *worker(void *data)
{
while (1) {
remove request from queue
service request
close connection
}
Page 126
134Computer Science 213© 2006 Donald Acton
Queue Access RulesQueue Access Rules
Observations:– There is a single queue of requests
accessed by both the workers and main thread
– Queue has a maximum size– Main thread can only add to queue if
there is room– Worker threads can only remove
something from the queue if something is there
Page 127
135Computer Science 213© 2006 Donald Acton
ProblemsProblems
• How does the main thread know if the queue is full?
• How do worker threads know if there is work to do?
Page 128
136Computer Science 213© 2006 Donald Acton
Try 1: A Single SemaphoreTry 1: A Single Semaphore
• Suppose you had a single semaphore, could one determine if there was work to do?
Page 129
137Computer Science 213© 2006 Donald Acton
Semaphore TricksSemaphore Tricks
• The process/thread that does a P() doesn’t have to be the one to do the V()
• Multiple V()’s can be done to increase the semaphore count – This produces a counting semaphore
and can be used when there are multiple units of a resource
Page 130
138Computer Science 213© 2006 Donald Acton
Try 2 SemaphoresTry 2 Semaphores
Main ThreadP(nonempty);
Start worker(s)
while (1) {
P(empty);
add req
V(nonempty);
}
Worker Thread
while (1) {
P(nonempty);
remove req
V(empty);
}
Page 131
139Computer Science 213© 2006 Donald Acton
More Workers and the Queue
More Workers and the Queue
• Works if there can be only 1 request• If we allowed N requests should we
have 1 semaphore per request/queue slot?
Page 132
140Computer Science 213© 2006 Donald Acton
Try 3 SemaphoresTry 3 Semaphores1. queue – semaphore
• Used to control the shared queue access
2. nonempty – counting semaphore• Initially 0• and indicates non-empty slots
3. empty – counting semaphore• Indicates empty slots initially N• Acquired by main() for each item
added
Page 133
141Computer Science 213© 2006 Donald Acton
Maintaining the QueueMaintaining the Queue
Main Threadwhile (1) {
P(empty);
P(queue);
add req
V(queue);
V(nonempty)
}
Worker Threadwhile (1){
P(nonempty);
P(queue);
remove req
V(queue);
V(empty);
}
Page 134
142Computer Science 213© 2006 Donald Acton
The Missing MethodsThe Missing Methods
• Status of a thread running or dead• Setting attributes
– Permitted memory usage– Scheduling policy
• Thread specific data• Concurrency control
– Mutexes– Condition variables– Reader/writer locking
Page 135
143Computer Science 213© 2006 Donald Acton
When to use fork()When to use fork()
• The task to be performed is logically separate from the “parent’s”
• Protection needed between children• e.g. command execution for a shell
– Shell doesn’t know how long command will take
– Commands are logically separate from the shell
Page 136
144Computer Science 213© 2006 Donald Acton
When to use threadsWhen to use threads
• The range of actions to be performed is small
• There needs to be information sharing between the “parent” and “child” or between children