if((stf.st_mode & S_IFMT) == S_IFREG){ /* dirname */ struct statvfs fs; char tmpbuf[MAXPATHLEN+1]; if(dirname == NULL){ /* 'to' - , */ strcpy(tmpbuf, to); if(s = strrchr(tmpbuf, '/')){ if(*tmpbuf != '/' || s != tmpbuf){ /* "../xxx" * : * , * "/" "/xxx" */ *s = '\0'; }else{ /* "/" "/xxx" */ if(s[1]) s[1] = '\0'; } dirname = tmpbuf; } else dirname = "."; } if(statvfs(dirname, &fs) >= 0){ size_t size = (geteuid() == 0 ) ? /* : */ fs.f_frsize * fs.f_bfree : /* : */ fs.f_frsize * fs.f_bavail; if(size < stf.st_size){ error("Not enough free space on %s: have %lu, need %lu", dirname, size, stf.st_size); close(fdin); return (-5); } } } if((fdout = creat(to, stf.st_mode)) < 0){ error("Can't create %s", to); close(fdin); return (-6); } else { fchmod(fdout, stf.st_mode); fchown(fdout, stf.st_uid, stf.st_gid); } . , 1992-95 - 211 - UNIX while (n = read (fdin, iobuf, sizeof iobuf)) { if(n < 0){ error ("read error"); code = (-7); goto done; } if(write (fdout, iobuf, n) != n) { error ("write error"); code = (-8); goto done; } } done: close (fdin); close (fdout); /* : */ if(stat(to, &stt) >= 0 && (stt.st_mode & S_IFMT) == S_IFREG){ if(stf.st_size < stt.st_size){ error("File has grown at the time of copying"); } else if(stf.st_size > stt.st_size){ error("File too short, target %s removed", to); unlink(to); code = (-9); } } return code; } int main(int argc, char *argv[]){ int i, code = 0; progname = argv[0]; if(argc < 3){ error("Usage: %s from... to", argv[0]); return 1; } for(i=1; i < argc-1; i++) code |= copyFile(argv[argc-1], argv[i]) < 0 ? 1 : 0; return code; } struct statvfs ( ): long: f_frsize f_blocks f_bfree ( ) f_bavail ( ) f_files I-nodes f_ffree I-nodes ( ) f_favail I-nodes ( ) char * f_basetype : ufs, nfs, ... . , 1992-95 - 212 - UNIX , - ( , ). ufs - UNIX file system BSD 4.x 6.4. . UNIX . . -  . ? ,  : - (). -,  - " ?", , , . -, ,  , - .  . . - , . , . "" , ; ( ). () . . ,  ( ) - . - gets, , . - . - , ( - : - ( ), , ...). - . , - - . , - . : . - , - , .   ( ,  , ). , - 5- , - 34-. - , , . , - . include- <signal.h> SIG. 1..NSIG-1, NSIG . , :   , . " ". , ; - , "". : - ,  kill(pid, sig); pid - () -, sig - . - - . - . , - , . . - - SIGINT SIGQUIT. ,   . - . - - . : . , 1992-95 - 213 - UNIX - ( ); - ( ), - , ; - ( ); -. . signal: #include <signal.h> void (*signal(int sig, void (*react)() )) (); react : SIG_IGN sig . ( SIGKILL) . SIG_DFL ( - ). _ void fr(gotsig){ ..... } /* */ ... signal (sig, fr); ... /* */ sig fr,  , - gotsig==sig. , ..  : ... signal (sig1, fr); signal(sig2, fr); ... fr() .  - SIG_DFL, fr. , - ,  .  ; . : G - ; D - (k), (i); C - : core, adb; F - ; S - , . G D C F S SIGTERM + k - + - SIGKILL - k - + - SIGINT + k - + - SIGQUIT + k + + - SIGALRM + k - + + SIGILL + k + - + SIGBUS + k + + + SIGSEGV + k + + + SIGUSR1, USR2 + i - + - SIGCLD + i - + + - SIGILL , : "" - "" SIGILL. - - ( ), . , . , 1992-95 - 214 - UNIX  . - SIGALRM alarm() (. ). - SIGCLD - - exit ( ). - ( ) , - wait (. ). - - . - SIG_IGN  SIG_DFL , .. - . - signal , void (*f)(); . - () (), . UNIX . , BSD ( - ). " ", . "" () , "": | sighold(sig); | : :<--- sig, : , | : "", . | : sigrelse(sig); |<----------- sig | , | .  sig,  . ( ): mask |= (1 << (sig - 1)); sig, , ( ). sighold "" , , . sigrelse "- " ( ) . sigset(sig, react); signal, , - react, sig ; react - sighold, - sigrelse. , , , "" , ( sigrelse). sigpause(sig); "" sighold(sig); ... sigpause(sig); ... sigrelse(sig); . , 1992-95 - 215 - UNIX sig. sig ( sigset), "" sig. UNIX POSIX sigaction, sigproc- mask, sigpending, sigsuspend. ! 6.4.1. , /etc/termcap. - SIGINT, "?". 'y' - - ; 'n' - ; 'r' - : lseek(fd,0L,0). SIGINT, . #include <signal.h> void onintr(sig){ /* sig - */ signal (sig, onintr); /* */ ... ... } main(){ signal (SIGINT, onintr); ... } . : signal (SIGINT, SIG_IGN); . , SIG_IGN - . 6.4.2. , - (read , wait -, ...),  . "" (-1) errno EINTR. - : , . alarm(sec), SIGALRM sec (0 - ): #include <signal.h> void (*oldaction)(); int alarmed; /* */ void onalarm(nsig){ alarmed++; } ... /* */ oldaction = signal (SIGALRM, onalarm); /* TIMEOUT . */ alarmed = 0; alarm ( TIMEOUT /* sec */ ); sys_call(...); /* */ // , // - onalarm if(alarmed){ // . // .. . }else{ alarm(0); /* */ // , // . } signal (SIGALRM, oldaction); , 10 . - " ", - "". read, gets ( getchar), . , 1992-95 - 216 - UNIX read. , fgets (gets) . /* * -. * FIFO- * . * * "" (.. , * ). * : * -2.2 FIFO-, * read() * . open()- * O_NDELAY, . * * : a.out /dev/tty * * . .. */ #define WAIT_TIME 5 /* 5 */ #define MAX_TRYS 5 /* 5 */ #define BSIZE 256 #define STDIN 0 /* */ #define STDOUT 1 /* */ #include <signal.h> #include <errno.h> #include <stdio.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> char buffer [ BSIZE ]; extern int errno; /* */ void timeout(nsig){ signal( SIGALRM, timeout ); } void main(argc, argv) char **argv;{ int fd, n, trys = 0; struct stat stin, stout; if( argc != 2 ){ fprintf(stderr, ": %s \n", argv[0]); exit(1); } if((fd = !strcmp(argv[1],"-")? STDIN : open(argv[1],O_RDONLY)) < 0){ fprintf(stderr, " %s\n", argv[1]); exit(2); } /* , , * hardcat aFile >> aFile * , - . * - (STDIN->STDOUT), * */ fstat(fd, &stin); fstat(STDOUT, &stout); if( !isatty(STDOUT) && stin.st_ino == stout.st_ino && stin.st_dev == stout.st_dev ){ fprintf(stderr, "\a == , %s.\n",argv[1]); exit(33); } . , 1992-95 - 217 - UNIX signal( SIGALRM, timeout ); while( trys < MAX_TRYS ){ alarm( WAIT_TIME ); /* 5 */ /* ... */ n = read( fd, buffer, BSIZE ); alarm(0); /* */ /* (, , ) */ /* : read() ? */ if( n < 0 && errno == EINTR ){ /* SIGALRM, * EINTR - * . */ fprintf( stderr, "\7timed out (%d )\n", ++trys ); continue; } if( n < 0 ){ /* */ fprintf( stderr, "read error.\n" ); exit(4); } if( n == 0 ){ /* */ fprintf( stderr, " EOF.\n\n" ); exit(0); } /* */ write( STDOUT, buffer, n ); trys = 0; } fprintf( stderr, " .\n" ); exit(5); } , , : #include <signal.h> void (*fsaved)(); ... fsaved = signal (sig, SIG_IGN); sys_call(...); signal (sig, fsaved); : sighold(sig); sys_call(...); sigrelse(sig);   . 6.4.3. sleep(n), n . alarm(n) () pause(),  . - , SIGALRM. alarm, - sleep (alarm , - ). . : . , 1992-95 - 218 - UNIX #include <sys/types.h> #include <stdio.h> #include <signal.h> int got; /* */ void onalarm(int sig) { printf( "\n" ); got++; } /* */ void sleep(int n){ time_t time(), start = time(NULL); void (*save)(); int oldalarm, during = n; if( n <= 0 ) return; got = 0; save = signal(SIGALRM, onalarm); oldalarm = alarm(3600); /* */ if( oldalarm ){ printf( " , %d .\n", oldalarm ); if(oldalarm > n) oldalarm -= n; else { during = n = oldalarm; oldalarm = 1; } } printf( "n=%d oldalarm=%d\n", n, oldalarm ); while( n > 0 ){ printf( "alarm(%d)\n", n ); alarm(n); /* SIGALRM n */ pause(); if(got) break; /* pause */ n = during - (time(NULL) - start); /* */ } printf( "alarm(%d) \n", oldalarm ); alarm(oldalarm); /* alarm(0) - */ signal(SIGALRM, save); /* */ } void onintr(int nsig){ printf( " SIGINT\n"); signal(SIGINT, onintr); } void onOldAlarm(int nsig){ printf( " \n"); } void main(){ int time1 = 0; /* 5, 10, 20 */ setbuf(stdout, NULL); signal(SIGINT, onintr); signal(SIGALRM, onOldAlarm); alarm(time1); sleep(10); if(time1) pause(); printf("!\n"); } . , 1992-95 - 219 - UNIX 6.4.4. "", 3 . #include <signal.h> #include <time.h> #include <stdio.h> void tick(nsig){ time_t tim; char *s; signal (SIGALRM, tick); alarm(3); time(&tim); s = ctime(&tim); s[ strlen(s)-1 ] = '\0'; /* '\n' */ fprintf(stderr, "\r%s", s); } main(){ tick(0); for(;;) pause(); } 6.5. . 6.5.1. , - ? char x[] = "hello"; int y[25]; char *p; main(){ int z = 12; int v; static int w = 25; static int q; char s[20]; char *pp; ... v = w + z; /* #1 */ } : x static data/DATA "hello" y static data/BSS {0, ..., 0} p static data/BSS NULL z auto stack 12 v auto stack w static data/DATA 25 q static data/BSS 0 s auto stack pp auto stack main static text/TEXT , : DATA -  ( - ). , ( ), . BSS (Block Started by Symbol) - . - 0 (NULL, "", '\0'). - , . . , 1992-95 - 220 - UNIX TEXT - , ().  - ; - -  . , , . adb sdb, ld. nm ߔ , strip ߔ size ߔ , (.. ), 3x , : stack - ( ). - , ( - -  , ).  ( , ). . data - , DATA BSS, . , - sbrk brk. , malloc() - . text - , TEXT . #1 . , : proc - - ; user - 4- - (u-area). , . 2 : ( , I- , - , I- , ...) . - . , - , . , - - ( " " - context switch). - . : : struct proc[] ####---------------> stack 1 #### data 2 text 3 : struct user 4 . , 1992-95 - 221 - UNIX , p_pid proc|-. : ( , ); p_uid - ; p_ppid - -; p_pri, p_nice - ; p_pgrp - ; p_wchan - ; p_flag p_stat - ; . proc include- <sys/proc.h>, user - <sys/user.h>. 6.5.2. fork() ()  :  , - . fork- : 0 - . pid - . fork . : main(){ while(1) if( ! fork()) pause(); } - - ( : , , -). fork 4 - . text , - (" ") . user  (. ). , fork() - . : #include <stdio.h> int pid, i, fd; char c; main(){ fd = creat( "TEST", 0644); if( !(pid = fork())){ /* : */ c = 'a'; for(i=0; i < 5; i++){ write(fd, &c, 1); c++; sleep(1); } printf(" %d \n", getpid()); exit(0); } /* else - */ c = 'A'; for(i=0; i < 5; i++){ write(fd, &c, 1); c++; sleep(1); } printf(" %d %d \n", getpid(), pid ); } TEST aABbCcDdEe AaBbcdCDEe , "" fork()  - . , - ____________________ |- pid=getpid(); . , 1992-95 - 222 - UNIX . - ! UNIX: fork() " - " - , -. , , 0, 1, 2: , . . fork(); 0 ## ---<--- 1 ## --->--- 2 ## --->--- ... ## fd ## --->--- TEST ... ## fork(); - - 0 ## ---<--- --->--- ## 0 1 ## --->--- ---<--- ## 1 2 ## --->--- ---<--- ## 2 ... ## ## ... fd ## --->--- TEST ---<--- ## fd ... ## | ## ... *--RWptr--> " " (. ). ,     , ,  / . , "" "" fd, R/W, .. - . pipe. : (!!!), , , , ... exec() ( , , ) ( ). 6.5.3. - , , . , ( a.out). exec, . : char *path; char *argv[], *envp[], *arg0, ..., *argn; execle(path, arg0, arg1, ..., argn, NULL, envp); execve(path, argv, envp); exec , , , path. path : /usr/bin/vi a.out ../mybin/xkick . , 1992-95 - 223 - UNIX "". ( - ), short int, " " (A_MAGIC), ( include- <a.out.h>). ld . , - . , . , , text data ( text ), - text (). - arg0, ..., argn - main . , - . - : char *argv[20]; argv[0]="ls"; argv[1]="-l"; argv[2]="-i"; argv[3]=NULL; execv( "/bin/ls", argv); execl( "/bin/ls", "ls","-l","-i", NULL): ( !) : stack, data, text ;  data text, path; - stack ( - ); user - ( , SIG_DFL SIG_IGN - SIG_DFL). main argv: void main( argc, argv ) int argc; char *argv[]; { ... } - argc - . NULL - .  - ( ); (pid); - ( ); - ; , , ( SIG_DFL). "" -  . , exec