project 2 hints. pthread_create synopsis #include int pthread_create(pthread_t *tid, const...

33
Project 2 Hints

Post on 21-Dec-2015

258 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

Project 2 Hints

Page 2: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 3: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 4: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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(&copy_tid, NULL, copy_file, (void *)myarg)) fprintf(stderr,"Thread creation was not successful: %s\n", strerror(error));}

Page 5: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 6: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 7: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 8: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 9: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 10: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 11: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 12: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 13: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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); }

… }

Page 14: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 15: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 16: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

UICI Implementation

u_open socket

bind

listen

u_listen accept

u_connect socket

connect

u_read read

u_write write

Page 17: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

Server Actions

• Socket

• Bind

• Listen

• Accept

Page 18: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 19: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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] };

Page 20: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 21: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

struct sockaddr

Contains family name and protocol specific

information

Page 22: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 23: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 24: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 25: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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; }

Page 26: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 27: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 28: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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; }

Page 29: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

Client Actions

• Socket

• Connect

Page 30: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 31: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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

Page 32: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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;

Page 33: Project 2 Hints. pthread_create SYNOPSIS #include int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*start_routine)(void *), void

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