Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Sysprog 12

945 views

Published on

Published in: Technology
  • Be the first to comment

Sysprog 12

  1. 1. C/C++ Linux System Programming <ul><ul><li>Session 12 </li></ul></ul><ul><ul><li>User-space System Programming </li></ul></ul><ul><ul><li> – session 2 </li></ul></ul>
  2. 2. Outline <ul><li>Signals </li></ul><ul><li>Job Control </li></ul><ul><li>Scheduling </li></ul><ul><li>IPC Intro </li></ul>
  3. 3. Sending Signals <ul><li>int kill(pid_t pid, int sig); </li></ul><ul><li>int raise(int sig); // = kill(getpid(), sig); </li></ul><ul><li>int sigqueue(pid_t pid, int sig, const union sigval value); // value is a payload (IPC w/data!!) </li></ul>
  4. 4. Handling Signals – old school <ul><li>Handler </li></ul><ul><ul><li>typedef void (*sighandler_t)(int); </li></ul></ul><ul><ul><li>sighandler_t signal(int signum, sighandler_t handler); </li></ul></ul><ul><ul><li>SIG_IGN / SIG_DFL </li></ul></ul><ul><ul><li>Example from sshd.c: </li></ul></ul>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. 5. Signal sets <ul><ul><li>int sigemptyset(sigset_t *set); // Init </li></ul></ul><ul><ul><li>int sigfillset(sigset_t *set); // Init with all </li></ul></ul><ul><ul><li>int sigaddset(sigset_t *set, int signum); </li></ul></ul><ul><ul><li>int sigdelset(sigset_t *set, int signum); </li></ul></ul><ul><ul><li>int sigismember(const sigset_t *set, int signum); </li></ul></ul><ul><ul><li>Non-POSIX: </li></ul></ul><ul><ul><ul><li>int sigisemptyset (sigset_t *set); </li></ul></ul></ul><ul><ul><ul><li>int sigorset (sigset_t *dest, sigset_t *left, sigset_t *right); </li></ul></ul></ul><ul><ul><ul><li>int sigandset (sigset_t *dest, sigset_t *left, sigset_t *right); </li></ul></ul></ul>
  6. 6. Masking <ul><li>Mask/Unmask </li></ul><ul><ul><li>int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); </li></ul></ul><ul><ul><li>how: SIG_BLOCK/SIG_UNBLOCK/SIG_SETMASK </li></ul></ul><ul><li>Check pending (temporarily masked) </li></ul><ul><ul><li>int sigpending(sigset_t *set); </li></ul></ul><ul><li>Waiting for a signal </li></ul><ul><ul><li>int pause(void); </li></ul></ul><ul><ul><li>int sigsuspend(const sigset_t *mask); </li></ul></ul>
  7. 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. 8. Versatile Signal Handling Interface <ul><li>int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); </li></ul><ul><li>Important sigaction fields: </li></ul><ul><ul><li>void (*sa_handler)(int); </li></ul></ul><ul><ul><li>void (*sa_sigaction)(int, siginfo_t *, void *); </li></ul></ul><ul><ul><li>sigset_t sa_mask; </li></ul></ul><ul><li>Important siginfo_t: </li></ul><ul><ul><li>si_signo , si_uid, si_value, si_addr </li></ul></ul>
  9. 9. 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); }
  10. 10. Some Signal Notes <ul><li>Behavior in fork </li></ul><ul><li>Behavior in exec </li></ul><ul><li>Process Group relevance </li></ul><ul><li>System call interruptions </li></ul><ul><li>Intro to race conditions </li></ul><ul><ul><li>Critical region </li></ul></ul><ul><ul><li>Reentrancy </li></ul></ul><ul><ul><li>Minimal work </li></ul></ul><ul><ul><li>Sigatomic_t </li></ul></ul>
  11. 11. system/popen <ul><li>fork/exec (/bin/sh) </li></ul><ul><li>Security hole </li></ul><ul><li>Signal blocking </li></ul>
  12. 12. Scheduling <ul><li>Time-sharing (timeslices) </li></ul><ul><li>States </li></ul><ul><li>Process table </li></ul><ul><li>Context switch </li></ul><ul><li>Priorities </li></ul><ul><li>Preemptive vs Cooperative Multitasking </li></ul><ul><li>Idle process </li></ul>
  13. 13. 2.4 Scheduling <ul><li>Nice values </li></ul><ul><ul><li>[-20,19], -20 is not nice, i.e. high priority </li></ul></ul><ul><ul><li>Time slice length & run queue order </li></ul></ul><ul><ul><li>Superuser to decrement </li></ul></ul><ul><li>int nice(int inc); // nice(0) is current </li></ul><ul><li>get/set priority </li></ul><ul><ul><li>int getpriority (int which, int who); </li></ul></ul><ul><ul><li>int setpriority (int which, int who, int prio); </li></ul></ul><ul><ul><li>Absolute </li></ul></ul><ul><ul><li>PRIO_RPOCESS, PRIO_PGRP, PRIO_USER </li></ul></ul>
  14. 14. Relinquishing CPU <ul><ul><li>int sched_yield </li></ul></ul><ul><ul><ul><li>why? </li></ul></ul></ul><ul><ul><ul><li>2.4 vs 2.6 (RT vs non-RT) </li></ul></ul></ul><ul><ul><li>Sleep </li></ul></ul><ul><ul><ul><li>unsigned int sleep(unsigned int seconds); </li></ul></ul></ul><ul><ul><ul><li>int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); </li></ul></ul></ul><ul><ul><ul><li>int usleep(useconds_t usec); </li></ul></ul></ul>
  15. 15. Real-time Scheduling <ul><li>Real-time - soft/hard </li></ul><ul><ul><li>determinism </li></ul></ul><ul><li>Priorities: 1-99, 0 non-RT </li></ul><ul><li>Scheduling classes </li></ul><ul><ul><li>Round-robin </li></ul></ul><ul><ul><li>FIFO </li></ul></ul><ul><li>Chrt </li></ul><ul><li>Be “nice” !!! </li></ul>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. 16. Processor Affinity <ul><li>SMP </li></ul><ul><li>Affinity: Which processor? </li></ul><ul><ul><li>By default, try the same and hereditary </li></ul></ul><ul><li>Do I care? -- Cache coherency </li></ul><ul><li>Do I really care? </li></ul><ul><ul><li>http://www.linuxjournal.com/article/6799 </li></ul></ul>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 &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. 17. Time <ul><li>Monotonic time / real time / process time </li></ul><ul><li>POSIX </li></ul><ul><ul><li>int clock_getres(clockid_t clk_id, struct timespec *res); </li></ul></ul><ul><ul><li>int clock_gettime(clockid_t clk_id, struct timespec *tp); </li></ul></ul><ul><ul><li>int clock_settime(clockid_t clk_id, const struct timespec *tp); </li></ul></ul>
  18. 18. System time <ul><li>get/set </li></ul><ul><ul><li>int gettimeofday(struct timeval *tv, struct timezone *tz); </li></ul></ul><ul><ul><li>int settimeofday(const struct timeval *tv, const struct timezone *tz); </li></ul></ul><ul><ul><li>time_t time(time_t *t); // seconds </li></ul></ul><ul><li>Printable </li></ul><ul><ul><li>char *ctime(const time_t *timep); //And family </li></ul></ul><ul><li>int adjtime(const struct timeval *delta, struct timeval *olddelta); </li></ul>
  19. 19. Examples from NTP gettimeofday(&tv, 0); epoch = tv.tv_sec; ... fprintf(stdout, &quot;# %s # %s&quot;, filename, ctime(&epoch)); curtime = time(0); printf(&quot;Starting: %s&quot;, ctime(&curtime));
  20. 20. Interval Timers <ul><li>Set a timer </li></ul><ul><li>Signal when expired </li></ul>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. 21. Example – ping.c static void noresp(int ign UNUSED_PARAM) { printf(&quot;No response from %s &quot;, hostname); exit(EXIT_FAILURE); } main() { ... signal(SIGALRM, noresp); alarm(5); /* give the host 5000ms to respond */ ... }
  22. 22. IPC Intro <ul><li>Share data </li></ul><ul><li>Synchronize </li></ul><ul><li>Mutual Exclusion </li></ul><ul><ul><li>Critical region </li></ul></ul><ul><ul><li>Semaphores </li></ul></ul>

×