+ All Categories
Home > Documents > Threads and Locking Ioctl operations. Threads Lightweight processes What’s wrong with processes?...

Threads and Locking Ioctl operations. Threads Lightweight processes What’s wrong with processes?...

Date post: 13-Dec-2015
Category:
Upload: marybeth-hensley
View: 266 times
Download: 0 times
Share this document with a friend
Popular Tags:
26
Threads and Locking Ioctl operations
Transcript

Threads and LockingIoctl operations

Threads

• Lightweight processes

• What’s wrong with processes?– fork() is expensive – 10 to 100 times slower– Inter process communication

• For returning information from child to parent

Threads…• Shared components

– Global memory– Instructions– Most data– Open descriptors (files, sockets etc)– Signal handlers

• Not shared…– Thread ID– Registers, Program counter, stack pointer– Stack– Errno– Signal mask– Priority

Creation

• Thread equivalent of fork()

• int pthread_create(pthread_t * thread,

pthread_attr_t * attr,

void * (*start_routine)(void *),

void * arg

);

• Returns 0 is OK, and non-zero (> 0) if error.

Termination

• Return from initial fuction.• void pthread_exit(void * status)• exit() called by any thread• main() returns

Waiting for child thread to exit

• int pthread_join(pthread_t tid, void **status)

• Equivalent of waitpid()

Detaching a thread

• The detached thread can act as daemon thread

• The parent thread doesn’t need to wait

• int pthread_detach(pthread_t tid)

• Detaching self :

pthread_detach(pthread_self())

Echo client-server

Server

S1 S2

ReadThread

WriteThread

ReadThread

WriteThread

listenfd

Read Write WriteReadClient1 Client2

Thread-based Echo Server

main()

{int listenfd, connfd;

int len;

/* Start the usual way */

listenfd = Socket(…);

Bind(listenfd, …);

Listen(listenfd, …)

for ( ; ; ) {len = addrlen;

connfd = Accept(listenfd, …);

/* Create a thread in service_func routine */

Pthread_create(NULL, NULL, service_func, (void *) connfd);

}

}

void * service_func(void *arg){

int local_connfd;

/* release parent from waiting */Pthread_detach(pthread_self());

/* extract connfd from argument */local_connfd = (int) arg;

/* receive and echo client’s message */str_echo(local_connfd);

/* Terminate the connection */Close(local_connfd);

return(NULL);

}

Thread-based Echo Client

int sockfd;FILE *fp;

main(){

pthread_t tid;fp = fopen(…);

/* Start the usual way */sockfd = Socket(…);…Connect(…);

/* Create a thread to send data */Pthread_create(&tid, NULL, write_func, NULL);

/* read data from sockfd */read_func();

/* wait for child thread */Pthread_join(tid, NULL);

}

void * write_func(void *arg){

char sendline[MAXLINE];

while( more data in fp)Read from fp into sendline[];write sendline[] into sockfd;

Shutdown(sockfd, SHUT_WR);return(NULL);

}

void read_func(){

char recvline[MAXLINE];

while ( more data from sockfd) read from sockfd into recvline[];write from recvline[] to stdout;

}

Mutex – for mutual exclusion

int counter = 0;

void *thread_func(void *arg){int val;

/* unprotected code – why? */val = counter;counter = val + 1;

return NULL;}

Mutex…int counter = 0;ptread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread_func(void *arg){int val;

/* protected by mutex */Pthread_mutex_lock( &mutex );val = counter;counter = val + 1;Pthread_mutex_unlock( &mutex );

return NULL;}

Condition Variable – for signaling

• Think of Producer – consumer problem

• Producers and consumers run in separate threads.

• Producer produces data and consumer consumes data.

• Consumer has to inform producer when data is available

Without condition variables

/* Globals */

int data_avail = 0;

int pthread_mutex_t data_mutex =PTHREAD_MUTEX_INITIALIZER;

void *producer(void *)

{

Pthread_mutex_lock(&data_mutex);

Produce data

Insert data into queue;

data_avail++;

Pthread_mutex_unlock(&data_mutex);

consume_data();

}

void *consumer(void *)

{

Pthread_mutex_lock(&data_mutex);

while( !data_avail )

/* do nothing – keep looping!!*/;

Extract data from queue;

if (queue is empty) data_avail = 0;

Pthread_mutex_unlock(&data_mutex);

consume_data();

}

With condition variables

int data_avail = 0;int pthread_mutex_t data_mutex =PTHREAD_MUTEX_INITIALIZER;int pthread_cont_t data_cond = PTHREAD_COND_INITIALIZER;

void *producer(void *) {

Pthread_mutex_lock(&data_mutex);

Produce data

Insert data into queue;data_avail++;

Pthread_cond_signal(&data_cond);

Pthread_mutex_unlock(&data_mutex);

consume_data();}

void *consumer(void *) {Pthread_mutex_lock(&data_mutex);

while( !data_avail ) {/* sleep on condition variable*/Pthread_cond_wait(&data_cond,

&data_mutex);}

/*woken up */Extract data from queue;if (queue is empty) data_avail = 0;

Pthread_mutex_unlock(&data_mutex);

consume_data();}

ioctl()

ioctl()

• Handles miscellaneous properties of a file/device referenced by a descriptor.– In our case, network interfaces.

• int ioctl(int fd, int request, void * arg)

– Socket operations– File operations– Interface configuration– ARP cache– Routing table

• SIOSPGRP/SIOGPGRP– set/get process/group ID of a socket

• FIONREAD– Return number of bytes in socket buffer

• SIOCGIFCONF– Get list of all interfaces

• SIOCGIFBRDADDR/ SIOCSIFBRDADDR– Get/set broadcast address

• SIOCGARP/SIOCSARP/SIOCDARP– Get/modify/delete ARP cache entry.

• SIOCADDRT/SIOCDELRT– Add/delete routes


Recommended