C/C++ Linux System Programming Session 12 User-space System Programming – session 2
Outline Signals Job Control Scheduling IPC Intro
Sending Signals int kill(pid_t pid, int sig); int raise(int sig); // = kill(getpid(), sig); int sigqueue(pid_t pid, int sig, const union sigval value); // value is a payload (IPC w/data!!)
Handling Signals – old school Handler typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); SIG_IGN / SIG_DFL Example from sshd.c: static void main_sigchld_handler(int sig) { int save_errno = errno; pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid < 0 && errno == EINTR)) ; signal(SIGCHLD, main_sigchld_handler); errno = save_errno; }
Signal sets int sigemptyset(sigset_t *set); // Init int sigfillset(sigset_t *set); // Init with all int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum); Non-POSIX: int sigisemptyset (sigset_t *set); int sigorset (sigset_t *dest, sigset_t *left, sigset_t *right); int sigandset (sigset_t *dest, sigset_t *left, sigset_t *right);
Masking Mask/Unmask int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); how: SIG_BLOCK/SIG_UNBLOCK/SIG_SETMASK Check pending (temporarily masked) int sigpending(sigset_t *set); Waiting for a signal int pause(void); int sigsuspend(const sigset_t *mask);
Masking Example - ssh/server_loop.c /* block SIGCHLD while we check for dead children */ sigemptyset(&nset); sigaddset(&nset, SIGCHLD); sigprocmask(SIG_BLOCK, &nset, &oset); if (child_terminated) { debug(&quot;Received SIGCHLD.&quot;); while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid < 0 && errno == EINTR)) if (pid > 0) session_close_by_pid(pid, status); child_terminated = 0; } sigprocmask(SIG_SETMASK, &oset, NULL); }
Versatile Signal Handling Interface int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); Important sigaction fields: void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; Important siginfo_t: si_signo , si_uid, si_value, si_addr
Example - inetd memset(&sa, 0, sizeof(sa)); sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGCHLD); sigaddset(&sa.sa_mask, SIGHUP); sa.sa_handler = retry_network_setup; sigaction_set(SIGALRM, &sa); sa.sa_handler = reread_config_file; sigaction_set(SIGHUP, &sa); sa.sa_handler = reap_child; sigaction_set(SIGCHLD, &sa); sa.sa_handler = clean_up_and_exit; sigaction_set(SIGTERM, &sa); sa.sa_handler = clean_up_and_exit; sigaction_set(SIGINT, &sa); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, &saved_pipe_handler); static void clean_up_and_exit(int sig UNUSED_PARAM){ ,,,, remove_pidfile(_PATH_INETDPID); exit(EXIT_SUCCESS); } int FAST_FUNC sigaction_set(int signum, const struct sigaction *act){ return sigaction(signum, act, NULL); }
Some Signal Notes Behavior in fork Behavior in exec Process Group relevance System call interruptions Intro to race conditions Critical region Reentrancy Minimal work Sigatomic_t
system/popen fork/exec (/bin/sh) Security hole Signal blocking
Scheduling Time-sharing (timeslices) States Process table Context switch Priorities Preemptive vs Cooperative Multitasking Idle process
2.4 Scheduling Nice values [-20,19], -20 is not nice, i.e. high priority Time slice length & run queue order Superuser to decrement int nice(int inc); // nice(0) is current get/set priority int getpriority (int which, int who); int setpriority (int which, int who, int prio); Absolute PRIO_RPOCESS, PRIO_PGRP, PRIO_USER
Relinquishing CPU int sched_yield why? 2.4 vs 2.6 (RT vs non-RT) Sleep unsigned int sleep(unsigned int seconds); int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); int usleep(useconds_t usec);
Real-time Scheduling Real-time - soft/hard determinism Priorities: 1-99, 0 non-RT Scheduling classes Round-robin FIFO Chrt Be “nice” !!! struct sched_param { /* ... */ int sched_priority; /* ... */ }; int sched_getparam (pid_t pid, struct sched_param *sp); int sched_setparam (pid_t pid, const struct sched_param *sp);
Processor Affinity SMP Affinity: Which processor? By default, try the same and hereditary Do I care? -- Cache coherency Do I really care? http://www.linuxjournal.com/article/6799 pid = atol(argv[1]); sscanf(argv[2], &quot;%08lx&quot;, &new_mask); if (sched_getaffinity(pid, len, &cur_mask) < 0) { perror(&quot;sched_getaffinity&quot;); return -1; } printf(&quot;pid %d's old affinity: %08lx\n&quot;, pid, cur_mask); if (sched_setaffinity(pid, len, &new_mask)) { perror(&quot;sched_setaffinity&quot;); return -1; } if (sched_getaffinity(pid, len, &cur_mask) < 0) { perror(&quot;sched_getaffinity&quot;); return -1; }
Time Monotonic time / real time / process time POSIX int clock_getres(clockid_t clk_id, struct timespec *res); int clock_gettime(clockid_t clk_id, struct timespec *tp); int clock_settime(clockid_t clk_id, const struct timespec *tp);
System time get/set int gettimeofday(struct timeval *tv, struct timezone *tz); int settimeofday(const struct timeval *tv, const struct timezone *tz); time_t time(time_t *t); // seconds Printable char *ctime(const time_t *timep); //And family int adjtime(const struct timeval *delta, struct timeval *olddelta);
Examples from NTP gettimeofday(&tv, 0); epoch = tv.tv_sec; ... fprintf(stdout, &quot;# %s\n# %s&quot;, filename, ctime(&epoch)); curtime = time(0); printf(&quot;Starting: %s&quot;, ctime(&curtime));
Interval Timers Set a timer Signal when expired int getitimer(int which, struct itimerval *value); int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); struct itimerval { struct timeval it_interval; /* next value */ struct timeval it_value; /* current value */ }; struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ }; unsigned int alarm(unsigned int seconds);
Example – ping.c static void noresp(int ign UNUSED_PARAM) { printf(&quot;No response from %s\n&quot;, hostname); exit(EXIT_FAILURE); } main() { ... signal(SIGALRM, noresp); alarm(5); /* give the host 5000ms to respond */ ... }
IPC Intro Share data Synchronize Mutual Exclusion Critical region Semaphores

Sysprog 12

  • 1.
    C/C++ Linux SystemProgramming Session 12 User-space System Programming – session 2
  • 2.
    Outline Signals JobControl Scheduling IPC Intro
  • 3.
    Sending Signals intkill(pid_t pid, int sig); int raise(int sig); // = kill(getpid(), sig); int sigqueue(pid_t pid, int sig, const union sigval value); // value is a payload (IPC w/data!!)
  • 4.
    Handling Signals –old school Handler typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); SIG_IGN / SIG_DFL Example from sshd.c: static void main_sigchld_handler(int sig) { int save_errno = errno; pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid < 0 && errno == EINTR)) ; signal(SIGCHLD, main_sigchld_handler); errno = save_errno; }
  • 5.
    Signal sets intsigemptyset(sigset_t *set); // Init int sigfillset(sigset_t *set); // Init with all int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum); Non-POSIX: int sigisemptyset (sigset_t *set); int sigorset (sigset_t *dest, sigset_t *left, sigset_t *right); int sigandset (sigset_t *dest, sigset_t *left, sigset_t *right);
  • 6.
    Masking Mask/Unmask intsigprocmask(int how, const sigset_t *set, sigset_t *oldset); how: SIG_BLOCK/SIG_UNBLOCK/SIG_SETMASK Check pending (temporarily masked) int sigpending(sigset_t *set); Waiting for a signal int pause(void); int sigsuspend(const sigset_t *mask);
  • 7.
    Masking Example -ssh/server_loop.c /* block SIGCHLD while we check for dead children */ sigemptyset(&nset); sigaddset(&nset, SIGCHLD); sigprocmask(SIG_BLOCK, &nset, &oset); if (child_terminated) { debug(&quot;Received SIGCHLD.&quot;); while ((pid = waitpid(-1, &status, WNOHANG)) > 0 || (pid < 0 && errno == EINTR)) if (pid > 0) session_close_by_pid(pid, status); child_terminated = 0; } sigprocmask(SIG_SETMASK, &oset, NULL); }
  • 8.
    Versatile Signal HandlingInterface int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); Important sigaction fields: void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; Important siginfo_t: si_signo , si_uid, si_value, si_addr
  • 9.
    Example - inetdmemset(&sa, 0, sizeof(sa)); sigaddset(&sa.sa_mask, SIGALRM); sigaddset(&sa.sa_mask, SIGCHLD); sigaddset(&sa.sa_mask, SIGHUP); sa.sa_handler = retry_network_setup; sigaction_set(SIGALRM, &sa); sa.sa_handler = reread_config_file; sigaction_set(SIGHUP, &sa); sa.sa_handler = reap_child; sigaction_set(SIGCHLD, &sa); sa.sa_handler = clean_up_and_exit; sigaction_set(SIGTERM, &sa); sa.sa_handler = clean_up_and_exit; sigaction_set(SIGINT, &sa); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, &saved_pipe_handler); static void clean_up_and_exit(int sig UNUSED_PARAM){ ,,,, remove_pidfile(_PATH_INETDPID); exit(EXIT_SUCCESS); } int FAST_FUNC sigaction_set(int signum, const struct sigaction *act){ return sigaction(signum, act, NULL); }
  • 10.
    Some Signal NotesBehavior in fork Behavior in exec Process Group relevance System call interruptions Intro to race conditions Critical region Reentrancy Minimal work Sigatomic_t
  • 11.
    system/popen fork/exec(/bin/sh) Security hole Signal blocking
  • 12.
    Scheduling Time-sharing (timeslices)States Process table Context switch Priorities Preemptive vs Cooperative Multitasking Idle process
  • 13.
    2.4 Scheduling Nicevalues [-20,19], -20 is not nice, i.e. high priority Time slice length & run queue order Superuser to decrement int nice(int inc); // nice(0) is current get/set priority int getpriority (int which, int who); int setpriority (int which, int who, int prio); Absolute PRIO_RPOCESS, PRIO_PGRP, PRIO_USER
  • 14.
    Relinquishing CPU intsched_yield why? 2.4 vs 2.6 (RT vs non-RT) Sleep unsigned int sleep(unsigned int seconds); int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); int usleep(useconds_t usec);
  • 15.
    Real-time Scheduling Real-time- soft/hard determinism Priorities: 1-99, 0 non-RT Scheduling classes Round-robin FIFO Chrt Be “nice” !!! struct sched_param { /* ... */ int sched_priority; /* ... */ }; int sched_getparam (pid_t pid, struct sched_param *sp); int sched_setparam (pid_t pid, const struct sched_param *sp);
  • 16.
    Processor Affinity SMPAffinity: Which processor? By default, try the same and hereditary Do I care? -- Cache coherency Do I really care? http://www.linuxjournal.com/article/6799 pid = atol(argv[1]); sscanf(argv[2], &quot;%08lx&quot;, &new_mask); if (sched_getaffinity(pid, len, &cur_mask) < 0) { perror(&quot;sched_getaffinity&quot;); return -1; } printf(&quot;pid %d's old affinity: %08lx\n&quot;, pid, cur_mask); if (sched_setaffinity(pid, len, &new_mask)) { perror(&quot;sched_setaffinity&quot;); return -1; } if (sched_getaffinity(pid, len, &cur_mask) < 0) { perror(&quot;sched_getaffinity&quot;); return -1; }
  • 17.
    Time Monotonic time/ real time / process time POSIX int clock_getres(clockid_t clk_id, struct timespec *res); int clock_gettime(clockid_t clk_id, struct timespec *tp); int clock_settime(clockid_t clk_id, const struct timespec *tp);
  • 18.
    System time get/setint gettimeofday(struct timeval *tv, struct timezone *tz); int settimeofday(const struct timeval *tv, const struct timezone *tz); time_t time(time_t *t); // seconds Printable char *ctime(const time_t *timep); //And family int adjtime(const struct timeval *delta, struct timeval *olddelta);
  • 19.
    Examples from NTPgettimeofday(&tv, 0); epoch = tv.tv_sec; ... fprintf(stdout, &quot;# %s\n# %s&quot;, filename, ctime(&epoch)); curtime = time(0); printf(&quot;Starting: %s&quot;, ctime(&curtime));
  • 20.
    Interval Timers Seta timer Signal when expired int getitimer(int which, struct itimerval *value); int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue); struct itimerval { struct timeval it_interval; /* next value */ struct timeval it_value; /* current value */ }; struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ }; unsigned int alarm(unsigned int seconds);
  • 21.
    Example – ping.cstatic void noresp(int ign UNUSED_PARAM) { printf(&quot;No response from %s\n&quot;, hostname); exit(EXIT_FAILURE); } main() { ... signal(SIGALRM, noresp); alarm(5); /* give the host 5000ms to respond */ ... }
  • 22.
    IPC Intro Sharedata Synchronize Mutual Exclusion Critical region Semaphores