lecture 12 overview
DESCRIPTION
Lecture 12 Overview. UDP Connected mode. A UDP socket can be used in a call to connect() This simply tells the O.S. the address of the peer No handshake is made to establish that the peer exists No data of any kind is sent on the network as a result of calling connect() on a UDP socket. - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/1.jpg)
Lecture 12 Overview
![Page 2: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/2.jpg)
UDP Connected mode
• A UDP socket can be used in a call to connect()
• This simply tells the O.S. the address of the peer
• No handshake is made to establish that the peer exists
• No data of any kind is sent on the network as a result of calling connect() on a UDP socket
2CPE 401/601 Lecture 12 : Socket Programming Issues
![Page 3: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/3.jpg)
Connected UDP
• Once a UDP socket is connected:– can use sendto() with a null dest address – can use write() and send()– can use read() and recv()
• only datagrams from the peer will be returned
– Asynchronous errors will be returned to the process
3
OS Specific, some won’t do this!
CPE 401/601 Lecture 12 : Socket Programming Issues
![Page 4: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/4.jpg)
Asynchronous Errors
• What happens if a client sends data to a server that is not running?– ICMP “port unreachable” error is generated by
receiving host and sent to sending host– The ICMP error may reach the sending host after
sendto() has already returned!– The next call dealing with the socket could return
the error
4CPE 401/601 Lecture 12 : Socket Programming Issues
![Page 5: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/5.jpg)
I/O Multiplexing
• We often need to be able to monitor multiple descriptors:
– a generic TCP client (like telnet)
– a server that handles both TCP and UDP
– Client that can make multiple concurrent requests • browser
5CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 6: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/6.jpg)
Example - generic TCP client
• Input from standard input should be sent to a TCP socket
• Input from a TCP socket should be sent to standard output
• How do we know when to check for input from each source?
6
STDIN
STDOUT
TC
P S
OC
KE
T
CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 7: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/7.jpg)
Options
• Use multiple processes/threads
• Use nonblocking I/O– use fcntl() to set O_NONBLOCK
• Use alarm and signal handler to interrupt slow system calls
• Use functions that support checking of multiple input sources at the same time
7CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 8: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/8.jpg)
Non blocking I/O• Tell kernel not to block a process if I/O requests
can not be completed• use fcntl() to set O_NONBLOCK:int flags;
flags = fcntl(sock,F_GETFL,0);
fcntl(sock,F_SETFL,flags | O_NONBLOCK);
• Now calls to read() (and other system calls) will return an error and set errno to EWOULDBLOCK
8CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 9: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/9.jpg)
Non blocking I/Owhile (! done) {
if ( (n=read(STDIN_FILENO,…)<0))
if (errno != EWOULDBLOCK)
/* ERROR */
else write(tcpsock,…)
if ( (n=read(tcpsock,…)<0))
if (errno != EWOULDBLOCK)
/* ERROR */
else write(STDOUT_FILENO,…)
}
9CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 10: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/10.jpg)
The problem with nonblocking I/O
• Using blocking I/O allows the OS to put your process to sleep when nothing is happening– Once input arrives, the OS will wake up your
process and read() (or whatever) will return
• With nonblocking I/O, the process will chew up all available processor time!!!
10CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 11: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/11.jpg)
Using alarmssignal(SIGALRM, sig_alrm);
alarm(MAX_TIME);
read(STDIN_FILENO,…);
...
signal(SIGALRM, sig_alrm);
alarm(MAX_TIME);
read(tcpsock,…);
...
11
A function you write
CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 12: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/12.jpg)
“Alarming” Issues
• What will happen to the response time ?
• What is the ‘right’ value for MAX_TIME?
12CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 13: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/13.jpg)
Select()
• The select() system call allows us to use blocking I/O on a set of descriptors – file, socket, …
• We can ask select to notify us when data is available for reading on either STDIN or a socket
13CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 14: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/14.jpg)
select()int select( int maxfd,
fd_set *readset,
fd_set *writeset,
fd_set *excepset,
const struct timeval *timeout);
• maxfd: highest number assigned to a descriptor• readset: set of descriptors we want to read from• writeset: set of descriptors we want to write to• excepset: set of descriptors to watch for exceptions• timeout: maximum time select should wait
14CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 15: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/15.jpg)
Using select()
• Create fd_set• Clear the whole thing with FD_ZERO• Add each descriptor you want to watch using
FD_SET
• Call select• when select returns, use FD_ISSET to see if I/O
is possible on each descriptor
15CPE 401/601 Lecture 12 : I/O Multiplexing
![Page 16: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/16.jpg)
System Calls and Errors
• In general, systems calls return a negative number to indicate an error– We often want to find out what error– Servers generally add this information to a log– Clients generally provide some information to the
user
16CPE 401/601 Lecture 12 : Error Handling
![Page 17: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/17.jpg)
What is fatal?
• How do you know what should be a fatal error?– Common sense– If the program can continue – it should
– if a server can't create a socket, or can't bind to it's port
• there is no sense continuing…
17CPE 401/601 Lecture 12 : Error Handling
![Page 18: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/18.jpg)
extern int errno;
• Whenever an error occurs, system calls set the value of the global variable errno– You can check errno for specific errors
• errno is valid only after a system call has returned an error– System calls don't clear errno on success– If you make another system call you may lose the
previous value of errno• printf makes a call to write!
18CPE 401/601 Lecture 12 : Error Handling
![Page 19: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/19.jpg)
General Strategies
• Include code to check for errors after every system call
• Develop "wrapper functions" that do the checking for you
• Develop layers of functions, each hides some of the error-handling details
19CPE 401/601 Lecture 12 : Error Handling
![Page 20: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/20.jpg)
Wrappers are great!
• Wrappers like those used in the text can make code much more readable
• There are always situations in which you cannot use the wrappers– Sometimes system calls are "interrupted" (EINTR)
• this is not always a fatal error !
20CPE 401/601 Lecture 12 : Error Handling
![Page 21: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/21.jpg)
Another approach
• Instead of simple wrapper functions, you might develop a layered system
• The idea is to "hide" the sockaddr and error handling details behind a few custom functions:– int tcp_client(char *server, int port);– int tcp_server(int port);
21CPE 401/601 Lecture 12 : Error Handling
![Page 22: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/22.jpg)
Layers and Code Re-use
• Developing general functions that might be re-used in other programs is obviously "a good thing"
• Layering is beneficial even if the code is not intended to be re-used:– hide error-handling from "high-level" code– hide other details– often makes debugging easier
22CPE 401/601 Lecture 12 : Error Handling
![Page 23: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/23.jpg)
The Best Approach to handling errors
• There is no best approach• Do what works for you
• Make sure you check all system calls for errors!– Not checking can lead to security problems!– Not checking can lead to bad grades on
assignments!
23CPE 401/601 Lecture 12 : Error Handling
![Page 24: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/24.jpg)
Lecture 13
Client/Server Programming
CPE 401 / 601
Computer Network Systems
slides are modified from Dave Hollingerslides are modified from Dave Hollinger
![Page 25: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/25.jpg)
Issues in Client/Server Programming
• Identifying the Server
• Looking up an IP address
• Looking up a well known port name
• Specifying a local IP address
• UDP/TCP client designCPE 401/601 Lecture 13 : Client/Server Issues 25
![Page 26: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/26.jpg)
Identifying the Server
• Options:– hard-coded into the client program– require that the user identify the server– read from a configuration file– use a separate protocol/network service to lookup
the identity of the server.
CPE 401/601 Lecture 13 : Client/Server Issues 26
![Page 27: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/27.jpg)
Identifying a TCP/IP server
• Need an IP address, protocol and port– We often use host names instead of IP addresses– usually the protocol is not specified by the user
• UDP vs. TCP
– often the port is not specified by the user
CPE 401/601 Lecture 13 : Client/Server Issues 27
![Page 28: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/28.jpg)
Services and Ports• Many services are available via “well known”
addresses (names)• There is a mapping of service names to port
numbers:
struct *servent getservbyname(
char *service, char *protocol );
• servent->s_port is the port number in network byte order
CPE 401/601 Lecture 13 : Client/Server Issues 28
![Page 29: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/29.jpg)
Specifying a Local Address
• When a client creates and binds a socket, it must specify a local port and IP address
• Typically clients don’t care what port it is on:haddr->port = htons(0);
CPE 401/601 Lecture 13 : Client/Server Issues 29
give me any available port !give me any available port !
![Page 30: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/30.jpg)
Local IP address
• A client can also ask the operating system to take care of specifying the local IP address:
haddr->sin_addr.s_addr=
htonl(INADDR_ANY);
CPE 401/601 Lecture 13 : Client/Server Issues 30
Give me the appropriate addressGive me the appropriate address
![Page 31: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/31.jpg)
UDP Client Design
• Establish server address (IP and port)• Allocate a socket• Specify that any valid local port and IP
address can be used
• Communicate with server (send, recv)• Close the socket
CPE 401/601 Lecture 13 : Client/Server Issues 31
![Page 32: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/32.jpg)
Connected mode UDP
• A UDP client can call connect() to establish the address of the server
• The UDP client can then use read() and write() or send() and recv()
• A UDP client using a connected mode socket can only talk to one server– using the connected-mode socket
CPE 401/601 Lecture 13 : Client/Server Issues 32
![Page 33: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/33.jpg)
TCP Client Design
• Establish server address (IP and port)• Allocate a socket• Specify that any valid local port and IP
address can be used
• Call connect()
• Communicate with server (read, write)• Close the connection
CPE 401/601 Lecture 13 : Client/Server Issues 33
![Page 34: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/34.jpg)
Closing a TCP socket
• Many TCP based application protocols support – multiple requests and/or – variable length requests over a single TCP
connection
• How does the server known when the client is done ?– and it is OK to close the socket ?
CPE 401/601 Lecture 13 : Client/Server Issues 34
![Page 35: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/35.jpg)
Partial Close
• One solution is for the client to shut down only it’s writing end of the socket
• shutdown() system call provides this function
shutdown(int s, int direction);– direction can be 0 to close the reading end or 1 to
close the writing end– shutdown sends info to the other process!
CPE 401/601 Lecture 13 : Client/Server Issues 35
![Page 36: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/36.jpg)
TCP sockets programming
• Common problem areas:– null termination of strings
– reads don’t correspond to writes
– synchronization (including close())
– ambiguous protocol
CPE 401/601 Lecture 13 : Client/Server Issues 36
![Page 37: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/37.jpg)
TCP Reads
• Each call to read() on a TCP socket returns any available data– up to a maximum
• TCP buffers data at both ends of the connection
• You must be prepared to accept data 1 byte at a time from a TCP socket!
CPE 401/601 Lecture 13 : Client/Server Issues 37
![Page 38: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/38.jpg)
Server Design
CPE 401/601 Lecture 13 : Client/Server Issues 38
Iterative
Small, fixed size requestsEasy to program
Iterative
Small, fixed size requestsEasy to program
Concurrent
Large or variable size requestsHarder to program
Typically uses more system resources
Concurrent
Large or variable size requestsHarder to program
Typically uses more system resources
![Page 39: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/39.jpg)
Server Design
CPE 401/601 Lecture 13 : Client/Server Issues 39
Connection-Oriented
EASY TO PROGRAMtransport protocol handles the tough stuff.
requires separate socket for each connection.
Connection-Oriented
EASY TO PROGRAMtransport protocol handles the tough stuff.
requires separate socket for each connection.
Connectionless
less overheadno limitation on number of clients
Connectionless
less overheadno limitation on number of clients
![Page 40: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/40.jpg)
Server Design
CPE 401/601 Lecture 13 : Client/Server Issues 40
IterativeConnectionless
IterativeConnectionless
IterativeConnection-Oriented
IterativeConnection-Oriented
ConcurrentConnection-Oriented
ConcurrentConnection-Oriented
ConcurrentConnectionless
ConcurrentConnectionless
![Page 41: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/41.jpg)
Statelessness
• State: Information that a server maintains about the status of ongoing client interactions
• Connectionless servers that keep state information must be designed carefully!
CPE 401/601 Lecture 13 : Client/Server Issues 41
Messages can be duplicated!Messages can be duplicated!
![Page 42: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/42.jpg)
The Dangers of Statefullness
• Clients can go down at any time
• Client hosts can reboot many times
• The network can lose messages
• The network can duplicate messages
CPE 401/601 Lecture 13 : Client/Server Issues 42
![Page 43: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/43.jpg)
Concurrent Server Design Alternatives
• One child per client
• Spawn one thread per client
• Preforking multiple processes
• Prethreaded Server
CPE 401/601 Lecture 13 : Client/Server Issues 43
![Page 44: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/44.jpg)
One child per client
• Traditional Unix server:– TCP: after call to accept(), call fork()– UDP: after recvfrom(), call fork()– Each process needs only a few sockets– Small requests can be serviced in a small amount
of time
• Parent process needs to clean up after children!!!! – call wait()
CPE 401/601 Lecture 13 : Client/Server Issues 44
![Page 45: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/45.jpg)
One thread per client
• Almost like using fork– call pthread_create instead
• Using threads makes it easier to have sibling processes share information– less overhead
• Sharing information must be done carefully– use pthread_mutex
CPE 401/601 Lecture 13 : Client/Server Issues 45
![Page 46: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/46.jpg)
Prefork()’d Server
• Creating a new process for each client is expensive
• We can create a bunch of processes, each of which can take care of a client
• Each child process is an iterative server
CPE 401/601 Lecture 13 : Client/Server Issues 46
![Page 47: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/47.jpg)
Prefork()’d TCP Server
• Initial process creates socket and binds to well known address.
• Process now calls fork() a bunch of times
• All children call accept()
• The next incoming connection will be handed to one child
CPE 401/601 Lecture 13 : Client/Server Issues 47
![Page 48: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/48.jpg)
Preforking
• Having too many preforked children can be bad
• Using dynamic process allocation instead of a hard-coded number of children can avoid problems
• Parent process just manages the children– doesn’t worry about clients
CPE 401/601 Lecture 13 : Client/Server Issues 48
![Page 49: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/49.jpg)
Sockets library vs. system call
• A preforked TCP server won’t always work if sockets is not part of the kernel– calling accept() is a library call, not an atomic
operation
• We can get around this by making sure only one child calls accept() at a time using some locking scheme
CPE 401/601 Lecture 13 : Client/Server Issues 49
![Page 50: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/50.jpg)
Prethreaded Server
• Same benefits as preforking
• Can also have the main thread do all the calls to accept() – and hand off each client to an existing thread
CPE 401/601 Lecture 13 : Client/Server Issues 50
![Page 51: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/51.jpg)
What’s the best server design?
• Many factors:– expected number of simultaneous clients– Transaction size
• time to compute or lookup the answer
– Variability in transaction size– Available system resources
• perhaps what resources can be required in order to run the service
CPE 401/601 Lecture 13 : Client/Server Issues 51
![Page 52: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/52.jpg)
Server Design
• It is important to understand the issues and options
• Knowledge of queuing theory can be a big help
• You might need to test a few alternatives to determine the best design
CPE 401/601 Lecture 13 : Client/Server Issues 52
![Page 53: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/53.jpg)
Threaded Programming
![Page 54: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/54.jpg)
Threads vs. Processes
• Creation of a new process using fork is expensive– Time – Memory
• A thread does not require lots of memory or startup time– called a lightweight process
Threads Programming 54
![Page 55: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/55.jpg)
fork()
Process A
GlobalVariables
Code
Stack
Process B
GlobalVariables
Code
Stack
fork()
![Page 56: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/56.jpg)
Process AThread 1
GlobalVariables
Code
Stack
Process AThread 2
Stack
pthread_create()
pthread_create()
![Page 57: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/57.jpg)
Multiple Threads
• Each process can include many threads.
• All threads of a process share: – memory
• program code and global data
– open file/socket descriptors– signal handlers and signal dispositions– working environment
• current directory, user ID, etc.
Threads Programming 57
![Page 58: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/58.jpg)
Thread-Specific Resources
• Each thread has it’s own:– Thread ID (integer)– Stack, Registers, Program Counter– errno
• Threads within the same process can communicate using shared memory.– Must be done carefully!
Threads Programming 58
![Page 59: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/59.jpg)
Posix Threads
• We will focus on Posix Threads– most widely supported threads programming
API.
• Solaris– you need to link with “-lpthread”
• On many systems, this also forces the compiler to link in re-entrant libraries – instead of plain C libraries
Threads Programming 59
![Page 60: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/60.jpg)
Threads Programming 60
Thread Creation
pthread_create(
pthread_t *tid,
const pthread_attr_t *attr,
void *(*func)(void *),
void *arg );
func is the function to be called.When func() returns the thread is terminated
![Page 61: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/61.jpg)
Threads Programming 61
pthread_create()
• The return value is 0 for OK.– positive error number on error
• Does not set errno !!!
• Thread ID is returned in tid
![Page 62: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/62.jpg)
pthread_t *tid
• The book says you can specify NULL for tid (thread ID), – this doesn't always work!
• Thread attributes can be set using attr,– including detached state and scheduling policy. – You can specify NULL and get the system
defaults.
Threads Programming 62
![Page 63: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/63.jpg)
Thread IDs
• Each thread has a unique ID, a thread can find out it's ID by calling pthread_self().
• Thread IDs are of type pthread_t which is usually an unsigned int. When debugging, it's often useful to do something like this:
• printf("Thread %u:\n",pthread_self());
Threads Programming 63
![Page 64: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/64.jpg)
Thread Arguments
• When func() is called the value arg specified in the call to pthread_create() is passed as a parameter– func can have only 1 parameter, and it can't be
larger than the size of a void *
• Complex parameters can be passed by using structures– The structure can't be a local variable of the function
calling pthread_create !!• threads have different stacks!
Threads Programming 64
![Page 65: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/65.jpg)
Thread args example
struct { int x,y } 2ints;
void *blah( void *arg) {
struct 2ints *foo = (struct 2ints *) arg;
printf("%u sum of %d and %d is %d\n",
pthread_self(), foo->x, foo->y,
foo->x+foo->y);
return(NULL);
}
Threads Programming 65
![Page 66: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/66.jpg)
Thread Lifespan
• Once a thread is created, – it starts executing function func() specified in
the call to pthread_create()
• If func() returns, thread is terminated
• A thread can also be terminated by calling pthread_exit()
• If main() returns or any thread calls exit()– all threads are terminated.
Threads Programming 66
![Page 67: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/67.jpg)
Detached State
• Each thread can be either joinable or detached.
• Detached: on termination all thread resources are released by the OS.
• A detached thread cannot be joined.
• No way to get at the return value of the thread.– a pointer to something: void *
Threads Programming 67
![Page 68: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/68.jpg)
Joinable Thread
• Joinable: on thread termination thread ID and exit status are saved by the OS
• One thread can "join" another by calling pthread_join – which waits (blocks) until a specified thread
exits
int pthread_join( pthread_t tid, void **status);
Threads Programming 68
![Page 69: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/69.jpg)
Shared Global Variables
int counter=0;
void *pancake(void *arg) {
counter++;
printf("Thread %u is number %d\n",
pthread_self(), counter);
}
main() {
int i; pthread_t tid;
for (i=0;i<10;i++)
pthread_create(&tid,NULL,pancake,NULL);
}Threads Programming 69
![Page 70: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/70.jpg)
DANGER! DANGER! DANGER!
• Sharing global variables is dangerous– two threads may attempt to modify the same
variable at the same time.
• Just because you don't see a problem when running your code doesn't mean it can't and won't happen!!!!
Threads Programming 70
![Page 71: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/71.jpg)
Avoiding Problems
• pthreads includes support for Mutual Exclusion primitives that can be used to protect against this problem.
• The general idea is to lock something before accessing global variables and to unlock as soon as you are done.
• Shared socket descriptors should be treated as global variables!!!
Netprog: Threads Programming 71
![Page 72: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/72.jpg)
pthread_mutex
• A global variable of type pthread_mutex_t is required:
pthread_mutex_t counter_mtx=PTHREAD_MUTEX_INITIALIZER;
• Initialization to PTHREAD_MUTEX_INITIALIZER
is required for a static variable!Threads Programming 72
![Page 73: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/73.jpg)
Threads Programming 73
Locking and Unlocking
• To lock use:pthread_mutex_lock(pthread_mutex_t &);
• To unlock use:pthread_mutex_unlock(pthread_mutex_t &);
• Both functions are blocking!
![Page 74: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/74.jpg)
Example Problem
• A server creates a thread for each client.
• No more than n threads (and therefore n clients) can be active at once.
• How can we have the main thread know when a child thread has terminated and it can now service a new client?
Threads Programming 74
![Page 75: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/75.jpg)
pthread_join() doesn’t help
• pthread_join requires that we specify a thread id. – is sort of like wait()
• We can wait for a specific thread,– but we can't wait for "the next thread to exit"
Threads Programming 75
![Page 76: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/76.jpg)
Use a global variable• When each thread starts up:
– acquires a lock on the variable (using a mutex)– increments the variable– releases the lock.
• When each thread shuts down:– acquires a lock on the variable (using a mutex)– decrements the variable– releases the lock.
Threads Programming 76
![Page 77: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/77.jpg)
What about the main loop?
active_threads=0;
// start up n threads on first n clients
// make sure they are all running
while (1) {
// have to lock/relase active_threads
if (active_threads < n)
// start up thread for next client
busy_ waiting(is_bad);
}Threads Programming 77
![Page 78: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/78.jpg)
Condition Variables
• pthreads support condition variables, – which allow one thread to wait (sleep) for an
event generated by any other thread.
• This allows us to avoid the busy waiting problem.
pthread_cond_t foo = PTHREAD_COND_INITIALIZER;
Threads Programming 78
![Page 79: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/79.jpg)
Condition Variables (cont.)
• A condition variable is always used with mutex.
pthread_cond_wait(pthread_cond_t *cptr,
pthread_mutex_t *mptr);
pthread_cond_signal(pthread_cond_t *cptr);
Threads Programming 79
don’t let the word signal confuse you -this has nothing to do with Unix signals
![Page 80: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/80.jpg)
Revised strategy
• Each thread decrements active_threads when terminating and calls pthread_cond_signal to wake up the main loop
• The main thread increments active_threads when each thread is started and waits for changes by calling pthread_cond_wait
• All changes to active_threads must be inside the lock and release of a mutex
• If two threads are ready to exit at (nearly) the same time– the second must wait until the main loop recognizes the first
• We don’t lose any of the condition signals
Threads Programming 80
![Page 81: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/81.jpg)
Global Variables
// global variable the number of active
// threads (clients)
int active_threads=0;
// mutex used to lock active_threads
pthread_mutex_t at_mutex = PTHREAD_MUTEX_INITIALIZER;
// condition var. used to signal changes
pthread_cond_t at_cond = PTHREAD_COND_INITIALIZER;
Threads Programming 81
![Page 82: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/82.jpg)
Child Thread Code
void *cld_func(void *arg) {
. . .
// handle the client
. . .
pthread_mutex_lock(&at_mutex);
active_threads--;
pthread_cond_signal(&at_cond);
pthread_mutex_unlock(&at_mutex);
return();
}
Threads Programming 82
![Page 83: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/83.jpg)
Main thread
// no need to lock yet
active_threads=0;
while (1) {
pthread_mutex_lock(&at_mutex);
while (active_threads < n ) {
active_threads++;
pthread_start(…)
}
pthread_cond_wait( &at_cond, &at_mutex);
pthread_mutex_unlock(&at_mutex);
}
IMPORTANT!Must happen while the mutex lock is
held.
Threads Programming 83
![Page 84: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/84.jpg)
Other pthread functions
• Sometimes a function needs to have thread specific data– eg, a function that uses a static local
• Functions that support thread specific data:pthread_key_create()
pthread_once()
pthread_getspecific()
pthread_setspecific()Threads Programming 84
![Page 85: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/85.jpg)
Thread Safe library functions
• You have to be careful with libraries.
• If a function uses any static variables (or global memory) it’s not safe to use with threads!
• The book has a list of the Posix thread-safe functions…
Threads Programming 85
![Page 86: Lecture 12 Overview](https://reader036.vdocuments.net/reader036/viewer/2022062806/56814f21550346895dbcb345/html5/thumbnails/86.jpg)
Thread Summary
• Threads are awesome, but dangerous.
• You have to pay attention to details or it's easy to end up with code that is incorrect – doesn't always work, or hangs in deadlock
• Posix threads provides support for – mutual exclusion, – condition variables and – thread-specific data.
Threads Programming 86