Upload
jared-stafford
View
223
Download
6
Embed Size (px)
Citation preview
Chapter 5.Connection Controls
Device == File ?
• Filenames• Properties• permission bits• system call– open, read, write, lseek, close, stat
Device == File ?
• Example: tty
modelink
owner Last_modified filenameinode
* Directory(d), Symbolic Link(l), Character Device(c), Block Device(b)
group
major # : Device Driver
minor # : Device
mode owner group size Last_modified filenamelink
(chapter 2)
Device == File ?
• Device Files and Inodes
Device != File ?
• Disk Files vs Terminal Files– Devices have their own attributes.• Connection attributes
- we can control attributes in a different way.
System call: fcntl
fcntl
PUR-POSE
Control file descriptors
INCLUDE #include <fcntl.h>#include <unistd.h>#include <sys/types.h>
USAGE int result = fcntl(int fd, int cmd);int result = fcntl(int fd, int cmd, long arg);int result = fcntl(int fd, int cmd, struct flock *lockp);
ARGS fdcmdarglock
the file descriptor to controlthe operation to performarguments to the operationlock information
RE-TURNS
-1 Other
if errordepends on operation
Change settings -Disk
• 3-steps for controlling filedesciptors
#include <fcntl.h>int s;s = fcntl(fd, F_GETFL); //step1. get flagss |= O_SYNC; //step2. modify flagsresult = fcntl(fd,F_SETFL,s); //step3. set flagsif(result == -1) perror(“setting SYNC”);
Change settings -Disk
• If two people log in at the same time, how can this Race Condition be avoided?
• Auto Append#include <fcntl.h>int s;s = fcntl(fd, F_GETFL);s |= O_APPEND;result = fcntl(fd,F_SETFL,s); if(result == -1) perror(“setting APPEND”);
Controlling File Descriptors
• fd = open(file_name, flags)– fd = open(fn, O_WRONLY|O_APPEND|O_SYNC);
• Flags– O_CREAT: Create the file if it does not exist.– O_TRUNC: If the file exists, truncate the file to
length zero.– O_EXCL: This flag is intended to prevent wo
processes from creating the same file. The second call returns -1.
Attribute of Terminal• A simple example
#include <stdio.h>main(){ int c, n = 0;
while((c = getchar()) != 'Q') printf("char %3d is %c code %d\n", n++, c, c);}$ ./a.outhellochar 0 is h code 104char 1 is e code 101char 2 is l code 108char 3 is l code 108char 4 is o code 111char 5 is code 10Q$
Change settings -Terminal
• The stty command
$stty erase X #make ‘X’ the erase key$stty –echo #type invisibly$stty erase @ echo #multiple requests
Change settings -Terminal
• 3-steps for changing terminl driver
#include <termios.h>
struct termios attribs;
tcgetattr(fd, &attribs); //step1. get attribssettings.c_lflag |= O_ECHO; //step2. modify attribstcsetattr(fd, TCSANOW, &attribs); //step3. send attribs
☞ TCSANOW, TCSADRAIN, TCSAFLUSH
function: tcgetattr
tcgetattr
PUR-POSE Read attributes from tty driver
INCLUDE #include <termios.h>#include <unistd.h>
USAGE int result = tcgetattr(int fd, struct termios *info);
ARGS fdinfo
the file descriptor connected to a terminalpointer to a struct termios
RE-TURNS
-1 0
if errorIf success
function: tcsetattr
tcsetattr
PURPOSE Set attributes in tty driver
INCLUDE #include <termios.h>#include <unistd.h>
USAGE int result = tcsetattr(int fd, int when, struct termios *info);
ARGSfdwheninfo
the file descriptor connected to a terminalwhen to change the settingspointer to a struct termios
RETURNS -1 0
if errorIf success
struct termios
struct termios {
tcflag_t c_iflag; /*input mode flags*/ tcflag_t c_oflag; /*output mode flags*/
tcflag_t c_cflag; /*control mode flags*/tcflag_t c_lflag; /*local mode flags*/cc_t c_cc[NCCS]; /*control charters*/speed_t c_ispeed; /*input speed*/speed_t c_ospeed; /*output speed*/
};
Example – Echo State
Example – change state#include <stdio.h>#include <termios.h>
#define oops(s,x) { perror(s);exit(x);}
main(int ac, char *av[]){
struct termios info;if(ac==1)
exit(0);if(tcgetattr(0, &info) == -1) //get attribs
oops(“tcgetattr”, 1);if(av[1][0] == ‘y’)
info.c_lflag |= ECHO; //turn on bitelse
info.c_lflag &= ~ECHO; //turn off bitif(tcsetattr(0,TCSANOW, &info) == -1) //set attribs
oops(“tcsetattr”, 2);}
Example – display attribs
Other Devices?
• System call: ioctlioctl
PUR-POSE Control a device
INCLUDE #include <sys/ioctl.h>
USAGE int result = ioctl(int fd, int operation (, arg…) );
ARGS
fdopera-tioninfo
the file descriptor connected to deviceOperation to performAny args required for the operation
RE-TURNS
-1 other
if errorDepends on device
Example
#include <stdio.h>#include <sys/ioctl.h>
int main(){ struct winsize wbuf;
if(ioctl(0, TIOCGWINSZ, &wbuf) != -1) printf("%d rows x %d cols\n", wbuf.ws_row, wbuf.ws_col); return 0;}
Chapter 6.Programming for Humans
Software tools• Programs that see no difference between disk
files and devices Ex) who, ls, sort, uniq, grep, tr, du, …
• Read stdin or files, Write to stdout and stderr.– $ sort > outputfile– $ sort x > /dev/lp
Device-Specific Program
• Programs that interact with specific devices
Ex) scanner, camera, cd-rom, …
• In this chapter, we make terminal-specific program. user-program !
User-Program
• Consider how the keystrokes are handled and output is processed.
• Common concerns of user program(a) immediate response to keys(b) limited input set(c) timeout on input(d) resistance to Ctrl-C
Modes of the terminal driver
• Raw mode- Sends entire sequence of characters.
• Canonical mode- Erase characters before sending the revised sequence to the reading process.
- Processes edit and delete.
Canonical mode
Modes of the terminal driver
• Example input Hello data DEL DEL DEL DEL world
• RAW mode output Hello data DEL DEL DEL DEL world
• Canonical mode output Hello world
Example#include <stdio.h>#include <ctype.h>int main( ){
int c;while((c = getchar( )) != EOF) {
if(c == ‘z’) c = ‘a’;else if(islower(c)) c++;putchar(c);
}}
$ ./a.outabxcd????efg <ctrl-C>
$ stty -icannon$ ./a.out????
$ stty icannon
* In Canonical Mode * In Non-Canonical Mode
Writing a User Program#!/bin/sh
while truedo
do_a_transactionif play_again # our targetthen
continuefibreak
done
Accept input
if “y” : return 0if “n” : return 1
y : loop backn : break• What play_again does is
• Prompt User with Question• If “y”, return 0• If “n”, return 1
First play_again#include <stdio.h>#include <termios.h>
#define QUESTION "Do you want another transaction“
int get_response(char *q){
printf("%s (y/n)?", q);while(1) {
switch(getchar()) {case 'y':case 'Y': return 0;case 'n':case 'N':case EOF: return 1;
}}
}
int main(){
int response;response = get_response(QUESTION);return response;
}
Second play_again: immediate re-sponse
int set_crmode(){ struct termios ttystate;
tcgetattr(0, &ttystate); ttystate.c_lflag &= ~ICANON; ttystate.c_cc[VMIN] = 1; tcsetattr(0, TCSANOW, &ttystate);}
int tty_mode(int how){ static struct termios original_mode; if(how == 0) { tcgetattr(0, &original_mode); return 0; } return tcsetattr(0, TCSANOW, &original_mode);}
int main(){ int response; tty_mode(0); set_crmode(); response = get_response(QUESTION); tty_mode(1); return response;}
Non-blocking mode
• Blocking– getchar() or read() wait for input
• How to set non-blocking– Use O_NDELAY in open or fcntl
• New play_again– Timeout feature.– Telling the terminal drive not to wait– No input found then sleep for few seconds and
look again for input– After three tries give up
New play_again/* play_again.c
purpose: Ask if you want another transactionMethod : set tty into chr-by-chr, no-echo mode
set tty into no-delay mode read char, return resultReturns: 0=> yes, 1=> no, 2=> timeoutBetter : rest the terminal mode on interrupt
*/
#include <stdio.h>#include <termios.h>#include <fcntl.h>#include <string.h>
#define ASK "Do you want another transaction“#define TRIES 3 /* maximum tries*/#define SLEEPTIME 2 /* time per try */#define BEEP putchar('\a') /* alert user */
/* play_again.c continued */
main( ){
int response;tty_mode(0); /* save current mode*/set_cr_noecho_mode(); /* set –icanon, echo */set_nodelay_mode(); /* noinput => EOF */
/* get some answer */response = get_response(ASK, TRIES);tty_mode(1); /* restore orig mode */
return response;}
/* purpose : ask a question and wait for y/n answer or maxtries * method : use getchsr and complain about non –y/n input * returns : 0=> yes, 1=> no, 2=> timeout */
get_response(char* question, int maxtries) {
int input;printf ("%s (y/n)?", question); /* ask*/fflush(stdout); /* force output */while(1)
{ sleep(SLEEPTIME); /* wait a bit*/input = tolower(get_ok_char()); /* get next char*/if (input == 'y') return 0; if (input == 'n') return 1;if (maxtries-- == 0) /* out time? */
return 2; /* say no */BEEP;
}}
/* skip over ilegal chars and return y,Y,n,N or EOP */
get_ok_char( ){
int c;while ((c = getchar())!=EOF && strchr("yYnN",c) == NULL) ;return c;
}
/* how == 0 => save current mode, how ==> 1 restore mode *//* this version handles termios and fcnt1 flags */
tty_mode(int how){
static struct termios original_mode;static int original_flags;if (how == 0) {
tcgetattr(0, &original_mode);orginal_flags= fcntl(0, F_GETFL);
} else {return tcsetattr(0, TCSANOW, &original_mode);fcnt1 (0, F_SETFL, orginal_flags);
}}
set_nodelay_mode( ){
int termflags;termflags = fcntl(0, F_GETFL); /* read current setting */termflags |= O_NDELAY; /* flip on nodelay bit */fcntl(0, F_SETFL, termflags); /* and install em */
}
set_cr_noecho_mode( ){
struct termios ttystate;tcgetattr(0, &ttystate); /* read current settings */ttystate.c_lflag &= ~ICANON; /* no buffering */ttystate.c_lflag &= ~ECHO; /* no echo either */ttystate.c_cc[VMIN] = 1; /* get 1 char at a time */tcsetattr(0, TCSANOW, &ttystate); /* install settings */
}
Others methods to implement timeouts
• What happens when Ctrl–C is pressed?$ make play_again3cc play_again3.c -o play_again3$ ./ play_again3Do you want another transaction (y/n)?Press Ctrl-C now$ logoutConnection to host closed bash$
• What is the problem of the sequence above?• Couldn’t restore ttys!
Ctrl-C kills process
User-Program
• Consider how the keystrokes are handle and output is processed.
• Common concerns of user program(a) immediate response to keys(b) limited input set(c) timeout on input(d) resistance to Ctrl-C
Signals
• What does Ctrl-C do?- Ctrl-C interrupts program
It generates a signal !
• Signal is a kernel mechanism• Simple and powerful
What does Ctrl-C do ?
What is signal ?
• Signal : One-word message Ex) go, stop, out, green light
• Each signal has a numerical code.– Interrupt signal is No. 2.
Where do signals come from?
• User, Kernel, other process
List of signals
/usr/include/signal.h
When a signal comes …
• Process have 3 choices:1. Accept
- signal(SIGINT, SIG_DFL)2. Ignore
- signal(SIGINT, SIG_IGN)3. Call a function
How to call a function
signal(signum, functionname);
signal
PURPOSE Simple signal handling
INCLUDE #include <signal.h>
USAGE result = signal(int signum, void(*action)(int))
ARGS signum : the signal to respond toaction : how to respond
RETURNS -1 if errorprevaction if success
Examples of signal handling
• sigdemo1.c : catching a signal#include <stdio.h>#include <signal.h>
main(){void f(int); int i;signal(SIGINT, f);for (i=0;i<5;i++){
printf("hello\n");sleep(1);
}}void f(int signum){ printf("OUCH!\n"); }
How sigdemo1 works
Run sigdemo1
$ ./sigdemo1hellohello (press Ctrl-C !)OUCH!hellohellohello
Examples of signal handling
• sigdemo2.c : ignoring a signal
#include <stdio.h>#include <signal.h>main(){
signal(SIGINT, SIG_IGN);printf("you can't stop me!\n");while(1){sleep(1);printf("haha\n");}
}
Run sigdemo2
$ ./sigdemo2you can’t stop me!hahahaha (press Ctrl-C !) (SIGINT)hahahaha (press Ctrl-\ !) (SIGQUIT)$
• What count is the number of printed “haha”s!• Why only four times?