550 likes | 677 Views
Chapter 5. Connection Controls. Device == File ?. Filenames Properties permission bits system call open, read, write, lseek , close, stat. Device == File ?. Example: tty. (chapter 2). Last_modified. owner. group. mode. filename. inode. link. mode. owner. group. size.
E N D
Device == File ? • Filenames • Properties • permission bits • system call • open, read, write, lseek, close, stat
Device == File ? • Example: tty (chapter 2) Last_modified owner group mode filename inode link mode owner group size Last_modified filename minor # : Device link major # : Device Driver * Directory(d), Symbolic Link(l), Character Device(c), Block Device(b)
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.
Change settings -Disk • 3-steps for controlling filedesciptors #include <fcntl.h> int s; s = fcntl(fd, F_GETFL); //step1. get flags s |= O_SYNC; //step2. modify flags result = fcntl(fd,F_SETFL,s); //step3. set flags if(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 #include <stdio.h> main() { int c, n = 0; while((c = getchar()) != 'Q') printf("char %3d is %c code %d\n", n++, c, c); } • A simple example $ ./a.out hello char 0 is h code 104 char 1 is e code 101 char 2 is l code 108 char 3 is l code 108 char 4 is o code 111 char 5 is code 10 Q $
Change settings -Terminal • The stty command $sttyerase 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> structtermiosattribs; tcgetattr(fd, &attribs); //step1. get attribs settings.c_lflag |= O_ECHO; //step2. modify attribs tcsetattr(fd, TCSANOW, &attribs); //step3. send attribs ☞ TCSANOW, TCSADRAIN, TCSAFLUSH
structtermios structtermios { tcflag_tc_iflag; /*input mode flags*/ tcflag_tc_oflag; /*output mode flags*/ tcflag_tc_cflag; /*control mode flags*/ tcflag_tc_lflag; /*local mode flags*/ cc_tc_cc[NCCS]; /*control charters*/ speed_tc_ispeed; /*input speed*/ speed_tc_ospeed; /*output speed*/ };
Example – change state #include <stdio.h> #include <termios.h> #define oops(s,x) { perror(s);exit(x);} main(int ac, char *av[]) { structtermios 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 bit else info.c_lflag&= ~ECHO; //turn off bit if(tcsetattr(0,TCSANOW, &info) == -1) //set attribs oops(“tcsetattr”, 2); }
Other Devices? • System call: ioctl
Example #include <stdio.h> #include <sys/ioctl.h> int main() { structwinsizewbuf; if(ioctl(0, TIOCGWINSZ, &wbuf) != -1) printf("%d rows x %d cols\n", wbuf.ws_row, wbuf.ws_col); return 0; }
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 anddelete.
Modes of the terminal driver • Example input Hello data DEL DELDELDEL world • RAW mode output Hello data DEL DELDELDEL 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); } } * In Canonical Mode * In Non-Canonical Mode $ stty-icannon $ ./a.out ???? $ sttyicannon $ ./a.out abxcd ???? efg <ctrl-C>
Writing a User Program #!/bin/sh while true do do_a_transaction if play_again # our target then continue fi break done Accept inputif “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“ intget_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 response int main() { int response; tty_mode(0); set_crmode(); response = get_response(QUESTION); tty_mode(1); return response; } intset_crmode() { structtermiosttystate; tcgetattr(0, &ttystate); ttystate.c_lflag &= ~ICANON; ttystate.c_cc[VMIN] = 1; tcsetattr(0, TCSANOW, &ttystate); } inttty_mode(int how) { static structtermiosoriginal_mode; if(how == 0) { tcgetattr(0, &original_mode); return 0; } return tcsetattr(0, TCSANOW, &original_mode); }
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 transaction Method : set tty into chr-by-chr, no-echo mode set tty into no-delay mode read char, return result Returns: 0=> yes, 1=> no, 2=> timeout Better : 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( ) { intresponse; 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( ) { intc; 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(inthow) { static structtermiosoriginal_mode; static intoriginal_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( ) { inttermflags; 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( ) { structtermiosttystate; 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_again3 cc play_again3.c -o play_again3 $ ./ play_again3 Do you want another transaction (y/n)? Press Ctrl-C now $ logout Connection to host closed bash$ • What is the problem of the sequence above? • Couldn’t restore ttys!
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 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: • Accept- signal(SIGINT, SIG_DFL) • Ignore- signal(SIGINT, SIG_IGN) • Call a function
How to call a function signal(signum, functionname);