Sysprog 11

50 %
50 %
Information about Sysprog 11

Published on April 27, 2009

Author: linuxawy

Source: slideshare.net

C/C++ Linux System Programming Session 11 User-space System Programming – session 1

Session 11

User-space System Programming

– session 1

Outline Generic OS Process concepts API for process creation and execution Signals Job Control Scheduling

Generic OS Process concepts

API for process creation and execution

Signals

Job Control

Scheduling

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

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

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

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

Process Program in Execution Address space PID pid_t getpid(void); Tools /proc ps top

Program in Execution

Address space

PID

pid_t getpid(void);

Tools

/proc

ps

top

Process Relationships Parent/Child Starting the process pid_t getppid(void); Cleanup responsibility Process group Job control

Parent/Child

Starting the process

pid_t getppid(void);

Cleanup responsibility

Process group

Job control

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:

Dup address space

Return child pid in parent, 0 in child

Copy on write (vfork)

gdb: set fork-follow-mode <parent/child>

busybox/ash.c:

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[]);

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[]);

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)?

Retains kernel representation

e.g. file descriptors, pid, priority

Loses user-space settings and byproducts

e.g. mapped files

Why not spawn (fork + exec)?

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

/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

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

fork inherits all

exec inherits real, switches effective on setuid bins

Saved ID: at time of exec

Rules

Root: anything

Other: saved or real

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);

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);

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);

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);

Signals Asynchronous IPC mechanism Atomic: scheduler's context Common signals Process behavior toward signals Ignore/Mask/Handle/Default SIGKILL/SIGSTOP

Asynchronous IPC mechanism

Atomic: scheduler's context

Common signals

Process behavior toward signals

Ignore/Mask/Handle/Default

SIGKILL/SIGSTOP

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

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

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));

Atexit

What pattern is this?

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

Wait family

pid_t wait(int *status);

pid_t waitpid(pid_t pid, int *status, int options);

Zombies: Fruit of negligent parents

SIGCHLD

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 {

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);

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);

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 */

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

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

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!!)

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 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; }

Handler

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

SIG_IGN / SIG_DFL

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);

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);

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

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) { 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); }

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

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

fork/exec (/bin/sh)

Security hole

Signal blocking

Scheduling Time-sharing (timeslices) States Process table Context switch Priorities Preemption

Time-sharing (timeslices)

States

Process table

Context switch

Priorities

Preemption

Scheduling (for now) nice/renice Relinquishing CPU schedule_yield sleep

nice/renice

Relinquishing CPU

schedule_yield

sleep

Real-time Scheduling Real-time soft/hard O(1) – deterministic performance Priorities Scheduling classes

Real-time

soft/hard

O(1) – deterministic performance

Priorities

Scheduling classes

Time

Alarms

#endif presentations

Add a comment

Related pages

Roland Schiradin - Sysprog - ZIVIT | XING

Sysprog. Freiberufler in Hofheim (Der Unternehmensname ... 11 Jahre 3 Monate. 01/2005 - heute Developer. UC4 21 Jahre 3 Monate. 01/1995 - heute ...
Read more

sysProg download | SourceForge.net

sysProg download. sysProg 2013-11-26 15:31:47 free download. sysProg ... KEEP ME UPDATED Get project updates, sponsored content from our select
Read more

z/OS R10 and R11 Sysprog Goody Bag - GSE Belux | Think ...

z/OS R10 and R11 Sysprog Goody Bag ... z/OS 1.11 Preview 22 z/OS R10&R11 Sysprog Goody Bag © 2009 IBM Corporation Improved cross-library tape load
Read more

Bob Rogers IBM Corporation August 11, 2011 Session Number 9723

z/OS 1.13 Sysprog Goody Bag Bob Rogers IBM Corporation August 11, 2011 Session Number 9723
Read more

www.ifmt.b-tu.de

10;10 1;2;3;4;5;6;7;8;9;10 2;3;4;5;6;7;8;9;10;11 3;4;5;6;7;8;9;10;11;12 4;5;6;7;8;9;10;11;12;13 5;6;7;8;9;10;11;12;13;14 6;7;8;9;10;11;12;13;14;15 7;8;9;10 ...
Read more

elk.informatik.fh-augsburg.de

... WWW: http://elk.informatik.fh-augsburg.de/hhweb/sysprog Letzte Änderung: 2014-11-18 ... Der Code befindet sich im Git Repository ``sysprog ...
Read more

SysProg - aktuell

Aktuelles zu Konzepte Systemnaher Programmierung für Studierende der Informatik (WS 2012 / 13) Vorlesung: fr. 09:50 h (A12.3.05) Übung: di. 11:30 h (A20 ...
Read more

Linux on z/VM System Programmer Survival Guide

Linux on z/VM System Programmer Survival Guide Jay Brenneman ... 2 9240 - Linux on z/VM SysProg Survival Guide 08/11/08 © 2008 IBM Corporation
Read more