1 / 24

CS 311 - Lecture 16 Outline

CS 311 - Lecture 16 Outline. Inter-process Communication (IPC) Pipes Signals. Inter-Process Communication (IPC). IPC methods in UNIX Intermediate/temporary files (often together with I/O redirection) Pipes - IPC between two processes forked by a common ancestor process (unnamed)

zaina
Download Presentation

CS 311 - Lecture 16 Outline

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. CS 311 - Lecture 16 Outline • Inter-process Communication (IPC) • Pipes • Signals CS 311 - Operating Systems 1

  2. Inter-Process Communication (IPC) • IPC methods in UNIX • Intermediate/temporary files (often together with I/O redirection) • Pipes - IPC between two processes forked by a common ancestor process (unnamed) • FIFOs (named pipes) - communication between any two processes on the same machine • Signals - communication between any two processes on the same machine • Sockets - communication between any two processes potentially separated by a network CS 311 - Operating Systems 1

  3. Between processes IPC • I/O redirection with dup2() allows you to redirect input and output between processes and files • How to redirect input between processes on the same machine? • Answers: • Use temporary/intermediate files • Writes to disk are slow • No good way to track when the other process is ready to receive or send new data • Better answer: use pipes! CS 311 - Operating Systems 1

  4. Pipes • Pipes provide a way to connect an output-only file descriptor in one process to an input-only file descriptor in another process Process 2 Process 1 read() fd_B write() fd_A CS 311 - Operating Systems 1

  5. Creating a Pipe • Pipes are possible because file descriptors are shared across fork() and exec() • A parent process creates a pipe • Results in two new open file descriptors, one for input and one for output • The parent process forks (and possibly execs) • The child process now reads from the input file descriptor, and the parent process writes to the output file descriptor • or vice-versa CS 311 - Operating Systems 1

  6. The pipe() function • Pipe() creates an unnamed pipe and returns two fds – one for read end (fd[0]) and other for write end (fd[1]). • Rules to processes on read end • If a process reads from a pipe whose write end has been closed, read() returns a 0 indicating end-of-input • If a process reads from an empty pipe whose write end is still open, it sleeps until some input is available. • If a process tries to read more bytes from a pipe than present, all of the contents are returned and read() returns the number of bytes read. CS 311 - Operating Systems 1

  7. The pipe() function • Rules to processes that write to a pipe • If a process writes to a pipe whose read end has been closed, the write fails and the writer is sent a SIGPIPE signal. The default action is to terminate the writer. • If a process writes fewer bytes to a pipe than the pipe can hold, the writer process will complete its system call without being preempted by another process. If a process writes more, then no guarantees of atomicity. CS 311 - Operating Systems 1

  8. Example code to create a pipe int r, p[2]; char message[512]; pid_t child1; if (pipe(p) == -1) { perror("pipe.c:pipe:"); exit(1); } child1 = fork(); switch (child1) { case 0: close(p[0]); /* (child) close the input file descriptor */ write(p[1], "hi parent process, this is the child!!", 41); exit(0); default: close(p[1]); /* (parent) close output file descriptor */ r = read(p[0], message, sizeof(message)); if (r > 0) { printf("Message received from child: %s\n", message); } exit(0); } CS 311 - Operating Systems 1

  9. flow control -read() • read() • if data is available • read() gets the data and returns immediately • The return value of the read() function tells you how many bytes were read - it may be less than you requested • if data is not available, read() will block waiting for data (your process execution is suspended until data arrives) CS 311 - Operating Systems 1

  10. flow control -write() • Write will not return until all the data has been written • Pipes have a certain size • Ex: only so much water will fit in a pipe between two points if data is not available, read() will block waiting for data (your process execution is suspended until data arrives) • If the pipe fills up, and there is no more room, write() will block until space becomes available (ie somebody reads the data from the pipe) CS 311 - Operating Systems 1

  11. Pipes • Write() puts bytes in the pipe, read() takes them out • It is possible to determine the size of the pipe - see fpathconf() or the book read() fd_B write() fd_A CS 311 - Operating Systems 1

  12. Programming note • Checking the return value of read() becomes very important. • Not just if return value is -1 • Also if return value is not equal to desired number of bytes read/written CS 311 - Operating Systems 1

  13. Closing pipes • What happens if a process closes their end of the pipe when the other process is still trying to read or write to the pipe? • Process A closes output pipe. • If Process B is currently blocked on a read(), then process B's read() will return 0 • Process B closes input pipe • If process A tries to write to the pipe, write() will return -1, and errno will be set to EPIPE. Also process A will be sent the SIGPIPE signal. • Very important to catch the SIGPIPE signal! CS 311 - Operating Systems 1

  14. Signals • When a user process wants to contact the kernel, it uses a system call • But how does the kernel initiate contact with a user process? • There are certain events that occur for which the kernel needs to notify a user process • The answer: • Signals! CS 311 - Operating Systems 1

  15. Signals • Have many similarities to "exceptions" in Java and C++ • Although they are much less flexible than exceptions • There are a fixed set of signals • You cannot create your own signals CS 311 - Operating Systems 1

  16. Signals are used for: • Kernel to process notifications: • Process has done something wrong (bus error, segmentation fault, etc) • A timer has expired (an alarm) • A child has completed executing • An event associated with the terminal has occurred (control-C, process trying to read from the background, etc) • The process on the other end of a communication link has gone away CS 311 - Operating Systems 1

  17. Notification of Wrongdoing • Many signals result from the process doing something it is not supposed to, for example: • Trying to read or write to an invalid memory address (bus error - SIGBUS and segmentation fault - SIGSEGV) • Floating-point error - SIGFPE • Trying to execute an illegal machine instruction - SIGILL • Executing an illegal system call - SIGSYS • Why is a signal needed? • Gives the process a chance to: • clean up before being terminated • ignore the event if appropriate CS 311 - Operating Systems 1

  18. Child has completed • Normally, the wait() and waitpid() calls will suspend until a child has completed executing • The signal allows a parent process to do other work instead of going to sleep and be notified when a child completes • Then when the SIGCHILD is received, the process can call wait() or waitpid() CS 311 - Operating Systems 1

  19. Terminating Processes • Several signals (SIGINT, SIGTERM, SIGKILL) provide a way to indicate that other processes should terminate • Sent from user process to another user process • SIGINT and SIGTERM can be caught by the receiver, and potentially ignored • SIGKILL can not be caught or ignored - guaranteed to end a process CS 311 - Operating Systems 1

  20. User-defined Signals • UNIX has reserved two signals for user-defined use • SIGUSR1 and SIGUSR2 • They have no special meaning to the kernel, but you can use them to signal between processes • Both the sending process and receiving process must agree on the meaning of SIGUSR1 and SIGUSR2 CS 311 - Operating Systems 1

  21. Receiving Signals • A process can decide what and how it wants to handle signals that are received. • A process can define a different reaction to each kind of signal. • There are three options to handling each type of signal: • 1) Ignore it - continue executing as if it had never occurred • 2) Take the default action. This is different for each type of signal • 3) Specify a function that should be called when a type of signal arrives CS 311 - Operating Systems 1

  22. sigaction() • Prototype: int sigaction(int signo, struct sigaction *act, struct sigaction *act) • First parameter is the signal type of interest • The second parameter is a pointer to a special sigaction structure • Describes the action to be taken upon receipt • The third parameter is a pointer to a another sigaction structure • The sigaction() function will use this pointer to write out what the setting were before the change was requested CS 311 - Operating Systems 1

  23. The sigaction structure struct sigaction { void (*sa_handler)(int); //Handler Function sigset_t sa_mask; //Additional set of signals to be blocked during execution of signal-catching function. int sa_flags; //Special flags to affect behavior of signal. void (*sa_sigaction)(int, siginfo_t *, void *); //Pointer to a signal-catching function }; CS 311 - Operating Systems 1

  24. (*sa_handler) - sigaction structure • The first attribute is set to one of three values: • SIG_DFL - take the default action • SIG_IGN - ignore the signal • A pointer to a function that should be called when this signal is received • Example: to ignore SIGINT signals main() { structsigaction act; act.sa_handler = SIG_IGN; sigaction(SIGINT, &act, NULL); while (1) { printf("sleeping…\n"); sleep(1); } exit(0); } CS 311 - Operating Systems 1

More Related