Operating Systems 2019W Lecture 6

From Soma-notes
Revision as of 03:33, 24 January 2019 by Soma (talk | contribs) (→‎Notes)

Video

Video from the lecture given on January 23, 2019 is now available.

Notes

Signals

  • processes can register signal handler functions for specific signals
  • When the kernel delivers a signal to a process, it runs the specified handler
  • The C library defines default handlers for all signals (except STOP and KILL)
  • When a process gets a signal, current execution is interrupted and the handler is invoked. When the handler terminates, the process continues where it was
  • Interrupted system calls return with an error EINTR.
  • If the process was blocked on a system call, the system call is interrupted and the handler is run.
  • The standard library can do different things with interrupted system calls. The SA_RESTART flag says to run the system call again. It only applies to a few system calls, primarily read-like ones. (So, when a read is interrupted, it is tried again.)


I/O redirection

To redirect standard in, out, or error, a shell does the following when running a command:

  • The shell does a fork
  • The parent (original process) calls wait on the child when it exits in order to get its return value. This wait can be synchronous (i.e., the wait system call blocks until the child terminates) or it can be asynchronous (the parent only calls wait when it receives a SIGCHLD signal).
  • The child process initializes standard in, out, and error by opening files and assigning them to file descriptors 0, 1, and 2
  • The child calls execve

To implement this, the hardest part is parsing the command line in order to figure out what files, if any, the child should open for file descriptors 0, 1, and 2.

Command-line arguments and environment variables

  • They are both stored in the memory of the process.
  • They are put there by execve, as part of loading a new executable into a process (and erasing everything that was in the process's address space).
  • execve doesn't necessarily change other aspects of process's state, thus they should be initialized by something else (normally, the C library)
  • In particular, the data structures associated with file descriptors (i.e., open files) are preserved across execve.

Code

reactive.c

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

void signal_handler(int the_signal)
{
        if (the_signal == SIGUSR1) {
                fprintf(stderr, "Ouch!\n");
                return;
        }
}

int main(int argc, char *argv[], char *envp[])
{
        int i = 1;
        
        struct sigaction signal_handler_struct;

        memset(&signal_handler_struct, 0, sizeof(signal_handler_struct));
        signal_handler_struct.sa_handler = signal_handler;
        signal_handler_struct.sa_flags = SA_RESTART;

        if (sigaction(SIGUSR1, &signal_handler_struct, NULL)) {
                fprintf(stderr, "Couldn't register SIGUSR1 handler.\n");
        }

        printf("Hello!\n");
        printf("Environment variables at %lx\n", (unsigned long) envp);
        printf("Argument variables at %lx\n", (unsigned long) argv);
        printf("Sitting around doing nothing...\n");

        while (1) {
                sleep(i);
                i++;
        }
        
        return 0;
}