Lecture 11, part 1: Inter-process communication (IPC)

Previous lecture Next lecture

Exam

Communication between processes

Important questions:

Processes revisited

Inter-process communication

Message-based communication

Based on two primitives:

send (destination, message)
receive (source, message)

Synchronization

... for message oriented communication

Addressing

... for message oriented communication

Additional properties

... for message oriented communication

Local IPC: Unix signals

Signals

Unix signals: logical view

Unix signals: implementation view

Unix signals: example

Stopping and Restarting Apache

To send a signal to the parent you should issue a command such as: kill -TERM cat /usr/local/apache/logs/httpd.pid``

TERM Signal: stop now

Sending the TERM signal to the parent causes it to immediately attempt to kill off all of its children. It may take it several seconds to complete killing off its children. Then the parent itself exits. Any requests in progress are terminated, and no further requests are served.

HUP Signal: restart now

Sending the HUP signal to the parent causes it to kill off its children like in TERM but the parent doesn't exit. It re-reads its configuration files, and re-opens any log files. Then it spawns a new set of children and continues serving hits.

USR1 Signal: graceful restart

The USR1 signal causes the parent process to advise the children to exit after their current request (or to exit immediately if they're not serving anything). The parent rereads its configuration files and re-opens its log files. As each child dies off the parent replaces it with a child from the new generation of the configuration, which begins serving new requests immediately.

Unix pipes

Programming Unix pipes

enum { READ=0, WRITE=1 }; /* indexes in fd array */
int main (int argc, char *argv[]) {
  int res, fd[2];
  if (pipe (fd) == 0) { /* create the pipe */
    res = fork ();
    if (res > 0) { /* parent process */
      close (fd[READ]); /* close reading side */
      dup2 (fd[WRITE], 1); /* redirect stdout to pipe */
      close (fd[WRITE]); /* release the descriptor */
      execlp (argv[1], argv[1], NULL); /* execute writer process */
    }
    else if (res == 0) { /* child process */
      close (fd[WRITE]); /* close writing side */
      dup2 (fd[READ], 0); /* redirect stdin from pipe */
      close (fd[READ]); /* release the descriptor */
      execlp (argv[2], argv[2], NULL); /* execute reader process */
    }
  }
  /* …handle errors here… */
}

Unix message queues

Programming Unix message queues

Unix message queue commands

Today, Unix message queues are rarely used, since – different to sockets (see the next section) – they are constrained to local communication. In addition, the related application code is less portable to other systems.

Lecture 11, part 2: IPC: Sockets and RPC

Sockets

Sockets: domains

Sockets: type and protocol

Socket programming

int bind (int socket,
  const struct sockaddr *address,
  socklen_t address_len);

Datagram sockets

ssize_t sendto (int socket, const void *message,
  size_t length, int flags,
  const struct sockaddr *dest_addr,
  socklen_t dest_len);
ssize_t recvfrom (int socket, void *buffer,
  size_t length, int flags,
  struct sockaddr *address,
  socklen_t *address_len);

Stream sockets

Client

int connect (int socket,
  const struct sockaddr *address,
  socklen_t address_len);

Server

Socket programming (2)

define PORT 6789
define MAXREQ (4096*1024)
char buffer[MAXREQ], body[MAXREQ], msg[MAXREQ];
void error(const char *msg) { perror(msg); exit(1); }

int main() {
  int sockfd, newsockfd;
  socklen_t clilen;
  struct sockaddr_in serv_addr, cli_addr;
  int n;
  sockfd = socket(PF_INET, SOCK_STREAM, 0); // Creates the socket
  if (sockfd < 0) error("ERROR opening socket");
  bzero((char *) &serv_addr, sizeof(serv_addr));
  serv_addr.sin_family = AF_INET;
  serv_addr.sin_addr.s_addr = INADDR_ANY;
  serv_addr.sin_port = htons(PORT);
  if (bind(sockfd, (struct sockaddr *) &serv_addr,
      sizeof(serv_addr)) < 0) { // Binds the socket to an address
    error("ERROR on binding");
  }
  listen(sockfd, 5);

  while (1) {
    clilen = sizeof(cli_addr);
    newsockfd = accept (sockfd, (struct sockaddr *) &cli_addr,
        &clilen); // Accepts a new connection
    if (newsockfd < 0) error("ERROR on accept");
    bzero(buffer,sizeof(buffer));
    n = read (newsockfd,buffer,sizeof(buffer)-1); // Reads the HTTP request
    if (n < 0) error("ERROR reading from socket");
    snprintf (body, sizeof (body),
        "<html>\n<body>\n"
        "<h1>Hello web browser</h1>\nYour request was\n"
        "
        "</body>\n</html>\n", buffer);
    snprintf (msg, sizeof (msg),
        "HTTP/1.0 200 OK\n"
        "Content-Type: text/html\n"
        "Content-Length: %d\n\n%s", strlen (body), body);
    // ^ Generates response
    n = write (newsockfd,msg,strlen(msg)); // Sends the response
    if (n < 0) error("ERROR writing to socket");
    close (newsockfd); // Closes the connection
  }
}

Remote procedure calls (RPC)

Conclusions

Two general classes of inter process communication: