Sysprog 12

903 views
851 views

Published on

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
903
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
11
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

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>

×