Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const...
-
date post
21-Dec-2015 -
Category
Documents
-
view
258 -
download
3
Transcript of Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const...
Project 2 Hints
pthread_create
SYNOPSIS#include <pthread.h>int pthread_create(pthread_t *tid, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);POSIX:THR
• tid points to thread ID• attr points to attributes of thread (NULL implies default
attributes)• start routine points to function thread calls when it begins
execution• start routine returns a pointer to void which is treated as
exit status by pthread_join
pthread_exit/pthread_join
SYNOPSIS#include <pthread.h>void pthread_exit(void *value_ptr);int pthread_join(pthread_t thread, void **value_ptr);
POSIX.THR• pthread_exit terminates the calling thread• The value_ptr parameter is available to a successful
pthread_join• However, the pthread_exit value_ptr parameter points to
data that exists after the thread exits, so it cannot be allocated as an automatic local variable
PTHREAD Example#include <stdio.h>
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <pthread.h>void main(void){ pthread_t copy_tid; int myarg[2]; int error; void *copy_file(void *arg); if ((myarg[0] = open("my.in", O_RDONLY)) == -1) perror("Could not open my.in"); else if ((myarg[1] = open("my.out", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) perror("Could not open my.out"); else if (error=pthread_create(©_tid, NULL, copy_file, (void *)myarg)) fprintf(stderr,"Thread creation was not successful: %s\n", strerror(error));}
Solaris 2.3 Service Times
Operation Microseconds
Unbound thread create
Bound thread create
fork()Unbound thread synchronize
Bound thread synchronize
Between process synchronize
52
350
1700
66
390
200
POSIX.SEM Semaphore Variables
• Semaphore variable is of type sem_t• Atomic operations for initializing, incrementing
and decrementing value• Unnamed semaphores – Can be used by a
single process or by children of a process that created it
• Named semaphores – Can be used by all processes
• Unnamed semaphores are similar in operation to pipes, and named semaphores are similar to named pipes
POSIX.SEM Semaphore Declaration
#include <semaphore.h>
sem_t sem;
• sem is a semaphore variable• POSIX.SEM does not specify underlying type of
sem_t• One possibility is for it to act like a file descriptor
that points to a local table and the table entries point to entries in a system file table
Semaphore OperationsSYNOPSIS#include <semaphore.h>int sem_init (sem_t *sem, int pshared, unsigned int value);int sem_destroy (sem_t *sem);int sem_wait (sem_t *sem);int sem_try (sem_t *sem);int sem_post (sem_t *sem);int sem_getvalue (sem_t *sem, int *sval);
POSIX.SEM• All semaphore functions return –1 and set errno on error• It is uncertain what semaphore functions return on success, but
usually 0• _POSIX_SEMAPHORES may be defined but system may NOT
support POSIX.SEM semaphores• POSIX.SEM semaphores are counting semaphores
sem_init
• Initializes semaphore to value parameter• If the value of pshared is non-zero, the
semaphore can be used between processes (the process that initializes it and by children of that process)
• If the value of pshared is zero, the semaphore can only be used by threads of a single process
• Think of sem as referring to a semaphore rather than being the semaphore itself
sem_destroy
• Destroys a previously initialized semaphore
• If sem_destroy attempts to destroy a semaphore that is being used by another process, it may return –1 and set errno to EBUSY – Unfortunately, the specifications do not require that the system detect this
sem_wait and sem_trywait
• sem_wait is a standard semaphore wait operation
• If the semaphore value is 0, sem_wait blocks until it can successfully decrement value or when interrupted such as by SIGINT
• sem_trywait is similar to sem_wait except instead of blocking on 0, it returns –1 and sets errno to EAGAIN
sem_post
• sem_post increments the semaphore value and is the classical semaphore signal operation
• sem_post must be async_signal_safe and may be invoked from a signal handler
Unnamed Semaphore Example#include <semaphore.h>…void main();{
…if (sem_init(&my_lock, 1, 1) {
perror(“could not initialize my_lock semaphore);…for (i = 1; i < n; ++i)
if (childpid = fork()) break;…if (sem_wait (&my_lock) == – 1) {
perror (“semaphore invalid); exit (1); }Critical Section
if (sem_post (&my_lock) == – 1) { perror (“semaphore done”); exit(1); }
… }
Connection-Oriented Protocol
• Server waits for a connection request from a client
• Once the connection is established, communication takes place using handles (file descriptors)
• The server address is not included in the user message
• Connection-oriented protocol has setup overhead
Single Port Strategy
• Simplest client-server communication takes place over a single communication port
• If client and server are on the same machine, the single port can be a FIFO
• On a network, port can be socket connection• When server starts up, it opens FIFO (or Socket)
and waits for client requests• When client needs service, it opens FIFO (or
Socket) and writes its request• Server then performs the service
Server Client Requests
UICI Implementation
u_open socket
bind
listen
u_listen accept
u_connect socket
connect
u_read read
u_write write
Server Actions
• Socket
• Bind
• Listen
• Accept
socket#include <sys/types.h>#include <sys/socket.h>int socket(int domain, int type, int protocol); • domain – selects protocol family to be used
AF_UNIX – Used on a single UNIX systemAF_INET – Used on internet and between remote hosts
• type – SOCK_STREAM – Reliable 2-way connection oriented typically
implemented with TCPSOCK_DGRAM – Connectionless communication using unreliable
messages of fixed length, typically implemented with UDP• Protocol – Specifies protocol to be used – There is usually only one
type so it is usually 0
bindSYNOPSIS#include <sys/types.h>#include <sys/socket.h>int bind (int s, const struct sockaddr *address, size_t address_len);
• s – File descriptor returned by the socket call• address_len – Number of bytes returned in the *address structure• *address – Contains family name and protocol-specific info
struct sockaddr_in {short sin_family;u_short sin_port;struct in_addr sin_addr;char sin_zero[8] };
bind (continued)
• Bind associates a socket endpoint or handle with a specific network connection
• Internet domain protocols specify the physical connection by a port number
• UNIX domain protocols specify the connection by a pathname
struct sockaddr
Contains family name and protocol specific
information
struct sockaddr_in
• The internet domain uses struct sockaddr_in for struct sockaddr
• sin_family – AF_INET• sin_port – is the port number using the network
byte ordering• sin_addr – INADDR_ANY allows communication
from any host• sin_zero – an array that fills out the structure so
that it has the same size as struct sockaddr
listen
SYNOPSIS#include <sys/types.h>#include <sys/socket.h>int listen (int s, int backlog);
• s – File descriptor returned by socket• backlog – number of pending client
requests allowed
sin_port field
• Represents the port using network byte ordering
• Machines that use a different byte ordering must do a conversion
• The macro host to network short (htons) can be used to convert port numbers
• htons should be used even when not necessary to maintain portability
u_open socket Implementationint u_open(u_port_t port){ int sock; struct sockaddr_in server; if (( u_ignore_sigpipe() != 0) || ((sock = socket(AF_INET, SOCK_STREAM,0)) < 0) return –1; server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = htons((short)port); if((bind(sock,(struct sockaddr *)&server,sizeof(server)) <0) || (listen(sock, MAXBACKLOG) < 0) return –1; return sock; }
acceptSYNOPSIS#include <sys/types.h>#include <sys/socket.h>int accept(int s, struct sockaddr *address, int *address_len);
• Parameters are similar to bind, except that accept fills in *address with info about the client making the connection
• sin_addr holds Internet address of client• *address_len – contains number of bytes of the buffer actually filled
in by the accept call• accept returns file descriptor for communicating with client• In parent-server model, server forks a child to handle the request
and resumes monitoring the file descriptor• Convert sin_addr to a name by calling gethostbyaddr
gethostbyaddr
SYNOPSIS#include <netdb.h>struct hostent *gethostbyaddr(const void
*addr, size_t len, int type);
• struct hostent includes a field h_name that is a pointer to the official host name
• On error, gethostbyaddr returns NULL and sets the external integer h_error
u_listen socket Implementationint u_listen(int fd, char *hostn)
{ struct sockaddr_in net_client; int len = sizeof(struct sockaddr); int retval; struct hostent *hostptr; while ( ((retval = accept(fd, (struct sockaddr *)(&net_client), &len)) == -1) && (errno == EINTR) ); if (retval == -1) return retval; hostptr = gethostbyaddr((char *)&(net_client.sin_addr.s_addr), 4, AF_INET); if (hostptr == NULL) strcpy(hostn, "unknown"); else strcpy(hostn, (*hostptr).h_name); return retval; }
Client Actions
• Socket
• Connect
connect
SYNOPSIS#include <sys/types.h>#include <sys/socket.h>int connect (int s, struct sockaddr *address, size_t
addres_len);
• Establishes a link between file descriptors and a well-known port on the remote server
• The sockaddr_in structure is filled in as it is with bind
gethostbynameSYNOPSIS#include <netdb.h>struct hostent *gethostbyname(const char *name);
• The host name string is converted to an appropriate Internet address by calling gethostbyname
• struct hostent includes two members of interest:– h_addr_list is an array of pointers to network
addresses used by this host – use the first one h_addr_list[0]
– h_length is filled with the number of bytes in the address
• On error gethostbyname returns NULL and sets the external integer h_error – macros exist to determine error
u_connect socket Implementation (top)
int u_connect(u_port_t port, char *hostn){ struct sockaddr_in server; struct hostent *hp; int sock; int retval; if ( (!(hp = gethostbyname(hostn)) || ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) ) return -1; memcpy((char *)&server.sin_addr, hp->h_addr_list[0],
hp->h_length); server.sin_port = htons((short)port); server.sin_family = AF_INET;
u_connect Implementation (bottom)while ( ((retval =
connect(sock, (struct sockaddr *)&server, sizeof(server))) == -1) && (errno == EINTR) ); if (retval == -1) { close(sock); return -1; } return sock; }
• Client creates a socket and makes the connection request• Client can be interrupted by a signal and loop reinitiates
the call• Program does not use strncpy for server.sin_addr since
the source may have an embedded zero byte• Once client and server establish a connection, they
exchange information using read and write