Sysprog 11
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Sysprog 11

on

  • 1,921 views

 

Statistics

Views

Total Views
1,921
Views on SlideShare
1,917
Embed Views
4

Actions

Likes
1
Downloads
18
Comments
0

2 Embeds 4

http://www.linkedin.com 3
http://www.slideshare.net 1

Accessibility

Categories

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Sysprog 11 Presentation Transcript

  • 1. C/C++ Linux System Programming
      • Session 11
      • User-space System Programming
      • – session 1
  • 2. Outline
    • Generic OS Process concepts
    • API for process creation and execution
    • Signals
    • Job Control
    • Scheduling
  • 3. Applicability
    • OS
    • POSIX
    • Portability
    • References
      • Modern Operating Systems - Tanenbaum
      • Advanced Programming in the UNIX Environment – Richard Stevens
      • Advanced Linux Programming – Mitchel et al
      • Linux System Programming – Robert Lowe
  • 4. errno
    • Typical return strategy on system calls
      • 0 on success
      • -1 on errno, errno is set
    • Global errno
      • char *strerror(int errnum);
      • char *strerror_r(int errnum, char *buf, size_t buflen);
      • void perror(const char *s);
    • Common error codes – context dependent
  • 5. Process
    • Program in Execution
    • Address space
    • PID
      • pid_t getpid(void);
    • Tools
      • /proc
      • ps
      • top
  • 6. Process Relationships
    • Parent/Child
      • Starting the process
        • pid_t getppid(void);
      • Cleanup responsibility
    • Process group
      • Job control
  • 7. fork – A new process
    • Dup address space
    • Return child pid in parent, 0 in child
    • Copy on write (vfork)
    • gdb: set fork-follow-mode <parent/child>
    pid = fork(); if (pid < 0) { TRACE((&quot;Fork failed, errno=%d&quot;, errno)); if (jp) freejob(jp); ash_msg_and_raise_error(&quot;can't fork&quot;); } if (pid == 0) forkchild(jp, /*n,*/ mode); else forkparent(jp, n, mode, pid);
    • busybox/ash.c:
  • 8. exec – Letting the child go
    • On success, no return
    • New address space
    • Execve – env
    • exec(l/v)(e)(p) – l: valist, v: char*[], e:env, p: PATH
      • int execve(const char *filename, char *const argv[], char *const envp[]);
  • 9. Exec Cont'd
    • Retains kernel representation
      • e.g. file descriptors, pid, priority
    • Loses user-space settings and byproducts
      • e.g. mapped files
    • Why not spawn (fork + exec)?
  • 10. User/Group Ids
    • /etc/password, /etc/group
    • setuid binaries
    • Minimal Privilege Concept
    • Real: Owner of original process
    • Effective: Currently executing (This is what is checked)
    • Remember stack overflows!!
      • http://insecure.org/stf/smashstack.html
  • 11. Ids and fork/exec
    • fork inherits all
    • exec inherits real, switches effective on setuid bins
    • Saved ID: at time of exec
    • Rules
      • Root: anything
      • Other: saved or real
  • 12. setuid API
    • POSIX
      • int setuid(uid_t uid); //all 3
      • int seteuid(uid_t euid); //eff
    • Non-POSIX
      • int setreuid(uid_t ruid, uid_t euid);
      • int setresuid(uid_t ruid, uid_t euid, uid_t suid);
  • 13. Config
    • Environment variables
      • char *getenv(const char *name);
      • int setenv(const char *name, const char *value, int overwrite);
      • int unsetenv(const char *name);
      • int putenv(char *string);
      • extern char **environ
    • Sysconf
      • long sysconf(int name);
  • 14. Signals
    • Asynchronous IPC mechanism
    • Atomic: scheduler's context
    • Common signals
    • Process behavior toward signals
      • Ignore/Mask/Handle/Default
      • SIGKILL/SIGSTOP
  • 15. exit – Process termination
    • Clean exit
      • Return from main
      • Exit call (why if I can just return?)
        • void exit(int status);
    • Exit status
      • EXIT_SUCCESS/EXIT_FAILURE
    • Non clean exit
  • 16. atexit static void mke2fs_clean_up(void) { if (ENABLE_FEATURE_CLEAN_UP && journal_device) free(journal_device); } int mke2fs_main (int argc, char **argv) { .... if (ENABLE_FEATURE_CLEAN_UP) atexit(mke2fs_clean_up); .... }
    • Atexit
    • What pattern is this?
    int atexit(void (*function)(void));
  • 17. wait – Responsible parenting
    • Wait family
      • pid_t wait(int *status);
      • pid_t waitpid(pid_t pid, int *status, int options);
    • Zombies: Fruit of negligent parents
    • SIGCHLD
  • 18. Wait example – sshd pid = fork(); if (pid == -1) { fatal(&quot;fork of unprivileged child failed&quot;); } else if (pid != 0) { debug2(&quot;Network child is on pid %ld&quot;, (long)pid); close(pmonitor->m_recvfd); pmonitor->m_pid = pid; monitor_child_preauth(authctxt, pmonitor); close(pmonitor->m_sendfd); /* Sync memory */ monitor_sync(pmonitor); /* Wait for the child's exit status */ while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) break; return (1); } else {
  • 19. Job Control
    • Process Group: for signals (consider | )
      • int setpgid(pid_t pid, pid_t pgid); // 0 current
    • Sessions: for terminal association
      • pid_t setsid(void); // not for pg leaders
    • Leaders
    • int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
  • 20. Interesting Example - busybox/init.c if (pid > 0) { /* Parent - wait till the child is done */ bb_signals(0 + (1 << SIGINT) + (1 << SIGTSTP) + (1 << SIGQUIT) , SIG_IGN); signal(SIGCHLD, SIG_DFL); waitfor(pid); /* See if stealing the controlling tty back is necessary */ if (tcgetpgrp(0) != getpid()) _exit(EXIT_SUCCESS); /* Use a temporary process to steal the controlling tty. */ pid = fork(); if (pid < 0) { message(L_LOG | L_CONSOLE, &quot;can't fork&quot;); _exit(EXIT_FAILURE); } if (pid == 0) { setsid(); ioctl(0, TIOCSCTTY, 1); _exit(EXIT_SUCCESS); } waitfor(pid); _exit(EXIT_SUCCESS); } /* Child - fall though to actually execute things */
  • 21. Daemons or Independent children
    • Reparenting to init – how?
    • No controlling tty – how do I make sure?
    • Some gotchas:
      • Directory
      • File descriptor
      • Logging
    • int daemon(int nochdir, int noclose); // Non-POSIX
  • 22. 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!!)
  • 23. Handling Signals – old school
    • Handler
      • typedef void (*sighandler_t)(int);
      • sighandler_t signal(int signum, sighandler_t handler);
      • SIG_IGN / SIG_DFL
    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; }
  • 24. 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);
  • 25. 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);
  • 26. 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); }
  • 27. 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
  • 28. 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) { servtab_t *sep; /* XXX signal race walking sep list */ for (sep = serv_list; sep; sep = sep->se_next) { if (sep->se_fd == -1) continue; switch (sep->se_family) { case AF_UNIX: unlink(sep->se_service); break; default: /* case AF_INET, AF_INET6 */ #if ENABLE_FEATURE_INETD_RPC if (sep->se_wait == 1 && is_rpc_service(sep)) unregister_rpc(sep); /* XXX signal race */ #endif break; } if (ENABLE_FEATURE_CLEAN_UP) close(sep->se_fd); } remove_pidfile(_PATH_INETDPID); exit(EXIT_SUCCESS); }
  • 29. 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
  • 30. system/popen
    • fork/exec (/bin/sh)
    • Security hole
    • Signal blocking
  • 31. Scheduling
    • Time-sharing (timeslices)
    • States
    • Process table
    • Context switch
    • Priorities
    • Preemption
  • 32. Scheduling (for now)
    • nice/renice
    • Relinquishing CPU
      • schedule_yield
      • sleep
  • 33. Real-time Scheduling
    • Real-time
      • soft/hard
      • O(1) – deterministic performance
    • Priorities
    • Scheduling classes
  • 34. Time
  • 35. Alarms