I/O Multiplexing & Threads

 

·       Select

·       Concurrent Client

·       Concurrent TCP Server Using Select

·       Poll

·       Concurrent TCP Server Using Poll

·       Threads & Synchronization

·       Shared Memory & Forking

 


 

âSelect:

 

n = select ( length, readset, writeset, exceptset, time)

 

values of  time:

 

       NULL      indifinate wait
          0            no-wait  (poll)
                    wait T  (sec + micro-sec)


Under what conditions a descriptor is ready?

ü ready for reading:

§  Receive buffer has data > low-water mark

(default is 1, set SO_RCVLOWWAT socket option to change).

§  Receive FIN from the other side.

§  A listen socket has a completed connection.

§  An error condition (e.g., receive RST ).

ü ready for writing:

§  Send buffer has space  > low-water mark

   (default is 2048, set SO_SNDLOWWAT socket option to change).

§  Sent FIN out (close write end).

§  An error condition.

ü ready for exception condition:

E.g., out-of-band date is received

 

 

 

 


âConcurrent Client

 

Example1:  echo client:

  strcliselect01.c   &  it is used in tcpcli01.c

 

  Server:     

% cd  /home/cs779/stevens3rd.book/unpv13e/tcpcliserv
% tcpserv
01  10123

  Client:
       %  cd  /home/cs779/stevens3rd.book/unpv13e/select
       %  tcpcli
01 127.0.0.1 10123
       %  tcpcli
01 127.0.0.1 10123  < infile  > outfile

      Problem:
      infile is NOT the same as outfile,   since we exit when stdin is done:

   if (Fgets(sendline, MAXLINE, fp) == NULL)  return;      

        

Example2:

 strcliselect02.c   &  it is used in tcpcli02.c
 The Problem above is fixed (use of  shutdown):

         % cd  /home/cs779/stevens3rd.book/unpv13e/select
         % tcpcli02  127.0.0.1 10123  < infile  > outfile

          if (Fgets(sendline, MAXLINE, fp) == NULL) {

          stdineof = 1;

          Shutdown(sockfd, SHUT_WR);   /* send FIN */

 



 

âConcurrent TCP Server using Select

 

ü Example3: tcpservselect01.c

 

Server:

      % cd  /home/cs779/stevens3rd.book/unpv13e/tcpcliserv
      % tcpservselect01 10123

 

Client:

      % cd  /home/cs779/stevens3rd.book/unpv13e/tcpcliserv
      %   tcpcli01 127.0.0.1  10123
     
(repeat for as many clients as you like)


     Problem: denial of service attack
          

%   tcpcli12  127.0.0.1 10123

 

    The user sends data without newline,

    The server will hung (blocked) forever!

 

 tcpcli012  uses  

 str_cli12.c  (this program dos not send newline!)

 



 

 


âPoll:

 

struct pollfd   client[MaxNofds];

 

client[i].fd = sockfd;

client[i].events = POLLRDNORM;

 

n = poll (struct  pollfd    client[], nfds_t  sizefds,  int  timeout);

 

values of timeout:


       INFTIM     indifinate wait

          0          no-wait  (poll)
         T          T  millisec


  if (client[i].revents & POLLRDNORM) {

          read (sockfd, ….);

  }

 

 


âConcurrent TCP Server using Poll



ü Example4: tcpservpoll01.c

 

Server:

      % cd  /home/cs779/stevens3rd.book/unpv13e/tcpcliserv
      % tcpservpoll01  10123

 

Client:

        % cd  /home/cs779/stevens3rd.book/unpv13e/tcpcliserv
        %   tcpcli01 127.0.0.1 10123  OR  telnet 127.0.0.1  10123
             
(repeat for as many clients as you like)

 

 




 

âThreads & Synchronization


 

Thread Functions:

pthread_create  (ThreadID, Priority, Starting Function, Function Args)

pthread_join    // similar to waitpid

pthread_self     // similar to getpid

pthread_detach  // not joinable

pthread_exit     // terminate a thread;

// calling exit() kills ALL threads. 
 
 

 

Simple Exampls:

à   tcpcli01.c uses (strclithread.c)  & 

à   tcpserv01.c:

 

 for ( ; ; ) {

       len = addrlen;

       connfd = Accept(listenfd, cliaddr, &len);

       Pthread_create(&tid, NULL, &doit, (void *) connfd);

    }

 

Server:

      % cd  /home/cs779/stevens3rd.book/unpv13e/threads
      % tcpserv01  10123

 

Client:

        % cd  /home/cs779/stevens3rd.book/unpv13e/threads
        %   tcpcli01 127.0.0.1 10123  OR  telnet 127.0.0.1  10123
             
(repeat for as many clients as you like)

 

 

Synchronization Functions:

    

pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;

 

Pthread_mutex_lock ( &mutex1 );

 

       { Critical Section}

 

Pthread_mutex_unlock ( &mutex1 );

 

Simple Exampl:

àThreadMutex.c

 

               pthread_mutex_lock(&mutex1);

               for (i = 1; i <= 1000000; i++) counter++;                       }

            pthread_mutex_unlock(&mutex1);

 

OR

 

               for (i = 1; i <= 1000000; i++) {

                  pthread_mutex_lock(&mutex1);

                    counter++;

                  pthread_mutex_unlock(&mutex1);

            }

 

%   cd  /home/cs779/stevens3rd.book/unpv13e/threads

%  ThreadMutex

 

Usage is ThreadMutex [0|1|2]

0 - no lock

1 - lock one by one

2 - lock all

 




 

 

âShared Memory & Forking


 

Functions:

The Process first creates shared memory segment and then attach to it:

segment id = shmget (IPC_PRIVATE, size, S_IRUSR | S_IWUSR);

char *sharedString = (char *) shmat (id, NULL, 0);

 

·       The process could write/read to/from the shared memory:

sprintf (shareString, "Writing to shared memory");

printf("%s", sharedStringy);

 

·       When done a process can detach the shared memory from its address space:

shmdt (sharedString);

 

·       When all done a process can  remove the shared memory and return it to the OS:

shmctl (segment_id, IPC_RMID, NULL);

 

 

Example: shmfork.c

#define SIZE 10

int
main()
{
   int             segment_id = shmget(IPC_PRIVATE, SIZE * sizeof(int), S_IRUSR | S_IWUSR);
   int            *sharedVar = (int *) shmat(segment_id, NULL, 0);
   int            *nonsharedVar = (int *) malloc(SIZE * sizeof(int));


   int             i;

   for (i = 0; i < SIZE; i++) {
      sharedVar[i] = 0;
      nonsharedVar[i] = 0;
   }


   if (fork() == 0) {
      for (i = 0; i < SIZE; i++) {
         sharedVar[i] += i;
         nonsharedVar[i] += i;
      }
      printf("\nChild : shared variables:- ");
      for (i = 0; i < SIZE; i++)
         printf("%d ", sharedVar[i]);
      printf(" non-shared variables:- ");
      for (i = 0; i < SIZE; i++)
         printf("%d ", nonsharedVar[i]);
      shmdt(segment_id);
      exit(0);
   }
   wait(NULL);

   printf("\nParent: shared variables:- ");
   for (i = 0; i < SIZE; i++)
      printf("%d ", sharedVar[i]);
   printf(" non-shared variables:- ");
   for (i = 0; i < SIZE; i++)
      printf("%d ", nonsharedVar[i]);
   printf("\n");

   shmdt(segment_id);

   shmclt(segment_id, IPC_RMID, NULL);
}

 

% cd /home/cs779/stevens3rd.book/unpv13e/threads

% shmfork

 

 

NOTE:

To list all shm segments ids:

% ipcs   –m

To remove a specific segment_id

% ipcrm  m   segment_id