csce 510 - systems programming lecture 15 shell 2 finally- filesystems again (note no lecture 13 –...

30
CSCE 510 - Systems Programming Lecture 15 Shell 2 Finally- Filesystems again (note no Lecture 13 – test 1) CSCE 510 Feb 25, 2013

Upload: anis-russell

Post on 13-Dec-2015

218 views

Category:

Documents


0 download

TRANSCRIPT

CSCE 510 - Systems

Programming

Lecture 15 Shell 2 Finally-Filesystems again (note no Lecture 13 – test 1)

CSCE 510 Feb 25, 2013

OverviewLast Time

Ext4 comments nfs vfs tmpfs Agile: User Stories, Configure/automake Advanced Signals

unreliable signals Why sigaction? Classes of signal handling

simple pay no attention: gcc graceful exit: DB interaction catch-start-over: bash, vim Full metal jacket: block all

except SIG_KILL, SIG_STOP

Today Classes of signal handling Job Control Terminal input char by

char (not line) Shell2 - Program

Virtual Memory File System: tmpfs

- CSCE 510 2013 -Slide - 3 - Advanced Shell Impl.

virtual file systems reside in memory (can you say fast)

usual suspects: (open(), read(), write(), link(), mkdir(), …

tmpfs – uses ram and the swap space mount -a [-fFnrsvw] [-t vfstype] [-O optlist]

Homework: Filesystems

- CSCE 510 2013 -Slide - 4 - Advanced Shell Impl.

Assuming 4K byte blocks what is the Maximum Size File in ext4?

Write a program or programs to find out/verify at what point does adding one character on our system adds three ( or maybe just more than 1) blocks? You can use TLPI/t_statvfs “/” to find the block size.

- CSCE 510 2013 -Slide - 5 - Advanced Shell Impl.

IntermissionTest 1 Post Mortem slides on website

TestingAgile User Stories – shell 1 examplesShell 2 – pipes, sigaction, jobs, terminals

- CSCE 510 2013 -Slide - 6 - Advanced Shell Impl.

SETJMP(3) Linux Programmer's Manual SETJMP(3)

NAME setjmp, sigsetjmp - save stack context for non-local goto

SYNOPSIS #include <setjmp.h>

int setjmp(jmp_buf env);

int sigsetjmp(sigjmp_buf env, int savesigs);

DESCRIPTION setjmp() and longjmp(3) are useful for dealing with errors and interrupts encountered in a low-level subroutine of a program. setjmp() saves the stack context/environment in env for later use by longjmp(3).The stack context will be invalidated if the function which called setjmp() returns.sigsetjmp() is similar to setjmp(). If, and only if, savesigs is non-zero, the process's current signal

Set_jmp revisited: proc/setjmp_vars.c

- CSCE 510 2013 -Slide - 7 - Advanced Shell Impl.

#include <stdlib.h>#include <setjmp.h>

static jmp_buf env;

static voiddoJump(int nvar, int rvar, int vvar){ printf("Inside doJump(): nvar=%d rvar=%d vvar=%d\n", nvar, rvar, vvar); longjmp(env, 1);}

int

main(int argc, char *argv[])

{

int nvar;

register int rvar; /* Allocated in register if possible */

volatile int vvar; /* See text */

nvar = 111;

rvar = 222;

vvar = 333;

if (setjmp(env) == 0) { /*Code executed after setjmp()*/

nvar = 777;

rvar = 888;

vvar = 999;

doJump(nvar, rvar, vvar);

} else { /* Code executed after longjmp() */

printf("After longjmp(): nvar=%d rvar=%d vvar=%d\n", nvar, rvar, vvar);

}

exit(EXIT_SUCCESS);

}

Volatile in C

- CSCE 510 2013 -Slide - 8 - Advanced Shell Impl.

In C, and consequently C++, the volatile keyword was intended to:

1. allow access to memory mapped devices2. allow uses of variables between setjmp and longjmp3. allow uses of sig_atomic_t variables in signal handlers. Operations on volatile variables are not atomic, nor do

they establish a proper happens-before relationship for threading. This is according to the relevant standards (C, C++, POSIX, WIN32),[2] and this is the matter of fact for the vast majority of current implementations. Thus, the usage of volatile keyword as a portable synchronization mechanism is discouraged by many C/C++ groups

http://en.wikipedia.org/wiki/Volatile_variable

Example of memory-mapped I/O in C

- CSCE 510 2013 -Slide - 9 - Advanced Shell Impl.

static int foo; void bar(void) {

foo = 0; while (foo != 255) ;

}

Optimizing compiler’s view

void bar_optimized(void) { foo = 0; while (true)

; }

http://en.wikipedia.org/wiki/Volatile_variable

StackOverflow why sigaction instead of signal ?

- CSCE 510 2013 -10 Advanced Shell Implementation

Use sigaction() unless you've got very compelling reasons not to do so.

The signal() interface has antiquity (and hence availability) in its favour, and it is defined in the C standard. Nevertheless, …

1. The signal() function does not block other signals from arriving while the current handler is executing; sigaction() can block other signals until the current handler returns.

2. The signal() function resets the signal action back to SIG_DFL (default) for almost all signals. (not on our Linux)

a. This means that the signal() handler must reinstall itself as its first action. b. It also opens up a window of vulnerability between the time when the signal

is detected and the handler is reinstalled during which if a second instance of the signal arrives, the default behaviour (usually terminate, sometimes with prejudice - aka core dump) occurs.

http://stackoverflow.com/questions/231912/what-is-the-difference-between-sigaction-and-signal

Unreliable signals: (old Man Signals) Examples/Unreliable.c

- CSCE 510 2013 -Slide - 11 - Advanced Shell Impl.

#include <stdio.h>#include <signal.h>

main(){

int onint(); /* SIGINT handler */ int i;

signal(SIGINT, onint); signal(SIGQUIT, onint);

for(i=0; ;i++) fprintf(stdout,"%d\n",i); }

intonint(int sig){ fprintf(stderr,"Rec SIG NUM=%d\n", sig); fprintf(stdout,"Rec SIG NUM=%d\n", sig); if(sig == SIGQUIT) exit(1); sleep(2); signal(SIGINT, onint);}

Unreliable Signals delivery picture

- CSCE 510 2013 -12 Advanced Shell Implementation

1. signal(SIGINT, onintr)2. rv=sigtab[SIGINT]3. sigtab[SIGINT]=onintr4. signal pending5. signal received6. transfer to onintr7. restore table to default sigtab[SIGINT]=SIGDFL8. sleep(2) // time to get killed9. signal(SIGINT, onintr)

rv=signal(SIGINT, onint);…infinite loop

Sigaction structure

- CSCE 510 2013 -13 Advanced Shell Implementation

struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };On some architectures a union is involved: do not assign to both sa_handler and sa_sigaction.

Classifying Programs by signal usage

- CSCE 510 2013 -Slide - 14 - Advanced Shell Impl.

Simple (programmer ignore) take default actions gcc,

graceful exit : Catch signal graceful exit catch signal longjmp to spot to remove temporary files, sync DB,

etc., close open fd

Catch signal and restart - consider a shell; what should it do when a SIGINT is received? vim, emacs, bash, …

Full-metal Jacket – block all signals that one can for a server or other daemon.

Examples/Sigaction/gracefulsiga.c

- CSCE 510 2013 -15 Advanced Shell Implementation

#include <stdio.h>#include <stdlib.h>#include <signal.h>

void onint(int ); /* SIGINT handler */struct sigaction act, *oldact;

main(){ int i; int rv; /* should be checked everytime */

sigset_t signal_mask; rv=sigfillset(&signal_mask);

act.sa_handler = onint; act.sa_mask = signal_mask; act.sa_flags = 0; act.sa_restorer = NULL;

rv=sigaction(SIGINT, &act, oldact); rv=sigaction(SIGQUIT, &act, oldact);

for(i=0; ;i++) fprintf(stdout,"%d\n",i); }

voidonint(int sig){ fprintf(stderr,"Graceful Exit:Recieved SIGNAL NUMBER =%d\n", sig); /* * Graceful exit type things removing temporary files etc. * */ exit(0);}

Graceful Exit with sigaction

- CSCE 510 2013 -16 Advanced Shell Implementation

#include <stdio.h>#include <stdlib.h>#include <signal.h>

void onint(int );/* SIGINT handler */

main(){

int i; int rv; /* should be checked everytime */

struct sigaction act, *oldact; sigset_t signal_mask; rv=sigfillset(&signal_mask);

act.sa_handler = onint; act.sa_mask = signal_mask; act.sa_flags = 0;

act.sa_restorer = NULL;

sigaction(SIGINT, &act, oldact); sigaction(SIGQUIT, &act, oldact);

for(i=0; ;i++) fprintf(stdout,"%d\n",i); }

voidonint(int sig){ fprintf(stderr,"STDERR:Recieved SIGNAL NUMBER =%d\n", sig); fprintf(stdout,"STDOUT:Recieved SIGNAL NUMBER =%d\n", sig); /* * Graceful exit type things removing temporary files etc. * */ exit(0)

Catch Signals and Start Over

- CSCE 510 2013 -17 Advanced Shell Implementation

Examples/Sigaction/restart.c

- CSCE 510 2013 -18 Advanced Shell Implementation

void onint(int );/* SIGINT handler */struct sigaction act, oldact;jmp_buf jbuf;__sigset_t signal_mask; /* sigset_t should work here but doesn't */ int save_mask; typedef struct cnode{ struct cnode *prev; char *word; struct cnode *next; } CMD_NODE, *CMD_PTR;

CMD_PTR buildCmd();

main(){ int i; int rv; /* should be checked everytime */ CMD_PTR c; rv=sigfillset((int *) &signal_mask);

act.sa_handler = onint; act.sa_mask = signal_mask; act.sa_flags = 0; act.sa_restorer = NULL;

rv=sigaction(SIGINT, &act, &oldact); // rv=sigaction(SIGQUIT, &act, &oldact); leave unset so that can use SIGQUIT to terminate rv=sigprocmask(SIG_UNBLOCK, NULL, &save_mask); // find sigmask for restoring

- CSCE 510 2013 -19 Advanced Shell Implementation

rv=setjmp(jbuf); // set up jbuf with registers etc,

for(i=0; ;i++){ fprintf(stdout,"%d-th prompt:\n",i); c = buildCmd(); // exec command c } }

CMD_PTR ReadCmd(){ return(NULL); // this should read a cmd}CMD_PTR PerformVarSubst(CMD_PTR c){ …}CMD_PTR PerformSubst(CMD_PTR c){ …;}

CMD_PTR buildCmd(){//a fake build command to illustrate throwing away several activation records off the stack CMD_PTR cmd; cmd = ReadCmd(); cmd = PerformSubst(cmd); // ...}

onint(int sig){ fprintf(stderr,"OK interrupted start over with prompt:Recieved SIGNAL NUMBER =%d\n", sig); /* * Restart at the start of the command loop */ sigprocmask(SIG_SETMASK, &save_mask, NULL );

// also should be handled with // sigsetjmp/siglongjmp

longjmp(jbuf, 1); //start over before printing prompt exit(0); // should never get here}

TLPI/signals/*.c

- CSCE 510 2013 -Slide - 20 - Advanced Shell Impl.

catch_rtsigs.c sigmask_longjmp.c cond

compilation sigsetjmp t_kill.c - kill implemnation demo_SIGFPE.c –div by 0

signal.c t_sigaltstack.c ignore_pending_sig.c signalfd_sigval.c t_sigqueue.c

intquit.c signal_functions.c t_sigsuspend.c nonreentrant.c sig_receiver.c t_sigwaitinfo.c ouch.c sig_sender.c siginterrupt.c sig_speed_sigsuspend.c

Job Control

- CSCE 510 2013 -21 Advanced Shell Implementation

^Z sends SIGSTOP

Terminal I/O

- CSCE 510 2013 -Slide - 22 - Advanced Shell Impl.

Fig 62-1 stty stty noecho

Terminal I/O

- CSCE 510 2013 -23 Advanced Shell Implementation

Typical input from keyboard is line buffered by terminal handler nothing input buffered till you type ‘\n’

Vi, less, Shells - character by character processing allowing up arrow and other arrows

Chapter 62 stty: canonical mode cbreak and raw mode (table 62-3)

Canonical Mode

- CSCE 510 2013 -Slide - 24 - Advanced Shell Impl.

input line-buffered if read requests less bytes remaining data saved for next

read

^D (EOT ) causes read to return EOF

line editing is enabled ERASE backspace/delete KILL ^U

Noncanonical Mode

- CSCE 510 2013 -Slide - 25 - Advanced Shell Impl.

MIN=0, TIME==0 (polling read)

MIN > 0, TIME==0 (blocking read)

MIN == 0, TIME>0 (read with timeout)

MIN > 0, TIME>0 (read with interbyte timeout)

Cooked, Raw, Cbreak

- CSCE 510 2013 -Slide - 26 - Advanced Shell Impl.

Table 62-3Feature Cooked Cbreak Raw

Input available line by line char by char char by char

Line editing? Yes No No

Signal generating chars interpreted? Yes Yes No

START/STOP interpreted? Yes Yes No

Other special chars interpreted? Yes No No

Other input processing? Yes Yes No

Other output processing? Yes Yes No

Input echoed? Yes maybe No

- CSCE 510 2013 -Slide - 27 - Advanced Shell Impl.

TERMIOS(3) Linux Programmer's Manual TERMIOS(3)

NAME termios, tcgetattr, tcsetattr, tcsendbreak, tcdrain, tcflush, tcflow, cfmakeraw, cfgetospeed, cfgetispeed, cfsetispeed, cfsetospeed, cfsetspeed - get and set terminal attributes, line control, get and set baud rate

SYNOPSIS #include <termios.h> #include <unistd.h>

int tcgetattr(int fd, struct termios *termios_p);

int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);

TLPI/tty

- CSCE 510 2013 -Slide - 28 - Advanced Shell Impl.

ls tty/*.cdemo_SIGWINCH.c no_echo.c tty_functions.cnew_intr.c test_tty_functions.c ttyname.c

Configure / Automake

- CSCE 510 2013 -Slide - 29 - Advanced Shell Impl.

download unpack

gunzip make* tar xvf make.tar

configure make

Git anyone? GitHub?

Configure sh scriptfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATHdo IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist,

# to save several forks. as_shell=$as_dir/$as_base

Shell 2 – write up in the mail tonight

- CSCE 510 2013 -Slide - 30 - Sigaction/Longjmp

Due Saturday of the week after we are back from Spring break. This is March 23.

multiple pipes character by character input for filename/command

completion Job control ? (let me think about this one.)