main,  , . exec , path , ( ), ( ), (), - ( ). . - exec ( - ). argv[0] path. , - ( ), . /bin/ls lr, lf, lx, ll.   - , argv[0] . envp - "" (. ). - ( , environ); (, - - - ) - . , - char **environ, - main (. ), getenv(). . , 1992-95 - 224 - UNIX fork exec , fork exec - , - : , /, ... " " . MS DOS, , fork, exec wait  spawn. -  spawn, - . 6.5.4.  void exit( unsigned char retcode ); . : stack, data, text, user ( ); , - , . - proc . ! "" - . retcode. - (, fork). , 0 , 1..255 . : - - . exit(-1); - ; -1 255. exit(errno);  exit, - : - main(), .. - exit() , retcode; -  . -, " ". 6.5.5. exit() - , . _exit(). - exit() , : void exit(unsigned code){ /* : */ printf(" , " " =%u\n", code); /* : */ _cleanup(); /* . * |= */ _exit(code); /* */ } int f(){ return 17; } void main(){ printf("aaaa\n"); printf("bbbb\n"); f(); /* : exit(77); */ } exit  main, . , exec-, - "", /lib/crt0.o. ( ): ... // argc, . main(argc, argv, envp); exit(); . , 1992-95 - 225 - UNIX ( GNU|-|-): int errno = 0; char **environ; _start(int argc, int arga) { /* OS and Compiler dependent!!!! */ char **argv = (char **) &arga; char **envp = environ = argv + argc + 1; /* ... - , * setlocale( LC_ALL, "" ); SCO UNIX */ exit (main(argc, argv, envp)); } int main(int argc, char *argv[], char *envp[]){ ... return 0; /* exit(0); */ } _start() a.out , ( ). exit() (  exit return) - . IBM PC 17, , . - , ( , ). 6.5.6. - . - wait : - . ,  - , . - - ! : "" , : int pid; unsigned short status; ... if((pid = fork()) == 0 ){ /* */ ... // -. ... // . exec(....); perror("exec "); exit(1); } /* */ while((pid = wait(&status)) > 0 ) printf(" pid=%d %d\n", pid, status >> 8); printf( " \n"); ____________________ |= _cleanup() , fopen(), "" , - , . - , , ( _exit). - . ____________________ |-|- GNU - , Free Software Founda- . , 1992-95 - 226 - UNIX wait |-  ( !). - - wait (pid) . "" - (-1). , , . status , , . #include <sys/types.h> #include <sys/wait.h> ... int status, pid; ... while((pid = wait(&status)) > 0){ if( WIFEXITED(status)){ printf( " %d %d\n", pid, WEXITSTATUS(status)); } else if( WIFSIGNALED(status)){ printf( " %d %d\n", pid, WTERMSIG(status)); if(WCOREDUMP(status)) printf( " core\n" ); /* core - adb */ } else if( WIFSTOPPED(status)){ printf( " %d %d\n", pid, WSTOPSIG(status)); } else if( WIFCONTINUED(status)){ printf( " %d \n", pid); } } ... , wait(NULL). - wait , (-1). while -  . , - ,  . , - "zombie" - " ". , - . -  , wait ? 1: /etc/init. -, 1 "" . init , wait(), ____________________ tion (FSF). - C++ g++ emacs. GNU - "gen- erally not UNIX" - UNIX . " UNIX, ". |- "" : - (""), , .. ; - ( ); - . - ( text) ( , ). - (.. "" ). - ("" ) . . , 1992-95 - 227 - UNIX ( , - ). init , . , : |pid=719,csh | if(!fork())------->--------* pid=723,csh | | wait(&status) exec("a.out",...) <-- a.out : main(...){ : | :pid=719,csh | pid=723,a.out () : | : exit(status) : } <---!--RIP | |pid=719,csh ,  - ,  . ,   , fork. 6.5.7. , wait . SIGSTOP, SIGTTIN, SIGTTOU, SIGTSTP. , SIGTSTP - CTRL/Z. SIGCONT. , , , . , - - SIGCLD . -  wait - . : void pchild(){ int pid, status; sighold(SIGCLD); while((pid = waitpid((pid_t) -1, &status, WNOHANG|WUNTRACED)) > 0){ dorecord: ___; } sigrelse(SIGCLD); /* Reset */ signal(SIGCLD, pchild); } ... main(){ ... /* SIGCLD pchild */ signal(SIGCLD, pchild); ... _; } waitpid ( wait), sighold-sigrelse, SIGCLD . . , 1992-95 - 228 - UNIX : dorecord:, , pchild , , , . . , pchild , . sighold ( ), sigrelse - ( -  . - waitpid). WNOHANG - " wait", ; (-1)". pchild : . WUNTRACED - " ". 6.5.8. , exec ( , fork exec dup2 , ). , ,  ? ( , - fd 0, 1 2; ). -, close fork- exec-. . : for(f = 3; f < NOFILE; f++) close(f); . , , exec  ( file-close-on-exec - fclex): #include <fcntl.h> int fd = open(.....); fcntl (fd, F_SETFD, 1); : fcntl (fd, F_SETFD, 0); : file - " ",  ( : char u_pofile[NOFILE]).  , : ... fcntl (fd, F_SETFD, 1); ... close(fd); ... int fd1 = open( ... ); fd1 fd, fd1 exec- , ! close(fd) fclex. 6.5.9.   (short *u_ttyp). - ( fork exec) , .   (int p_pgrp), . pgrp: kill( -pgrp, sig ); kill( 0, sig ); sig , . , 1992-95 - 229 - UNIX . : int pgrp = getpgrp(); "" . setpgrp(); : /* . : */ if(p_pgrp != p_pid) u_ttyp = NULL; /* -: */ p_pgrp = p_pid; /* new group */ , (t_pgrp). - , : /* */ if( p_pid == p_pgrp // && u_ttyp == NULL // .. && t_pgrp == 0 ){ // u_ttyp = &t_pgrp; t_pgrp = p_pgrp; } ( ). ( ) : t_pgrp=0; : c_cc[ VINTR ] DEL CTRL/C c_cc[ VQUIT ] CTRL/\ SIGINT SIGQUIT , .. kill( -t_pgrp, sig ); DEL. , setpgrp(), (.. != ). ( setpgrp),  ( ) - . -, - , , . 0, 1, 2 , - ( ). - /etc/getty ( "get tty" - ) - 1 - /etc/init- - , , - ; - - ( ). getty : void main(ac, av) char *av[]; { int f; struct termio tmodes; for(f=0; f < NOFILE; f++) close(f); /* , * . */ setpgrp(); /* */ . , 1992-95 - 230 - UNIX /* av[1] . */ open( av[1], O_RDONLY ); /* fd = 0 */ open( av[1], O_RDWR ); /* fd = 1 */ f = open( av[1], O_RDWR ); /* fd = 2 */ // ... // /etc/gettydefs. // , av[2]. // tmodes // ... . ioctl (f, TCSETA, &tmodes); // ... ... chdir (__); execl ("/bin/csh", "-csh", NULL); /* . , * . , 0,1,2 . */ } open - ( - ) - 0,1,2 -. - 0,1,2 . init - getty , /etc/getty /dev/tty01 m & /etc/getty /dev/tty02 m & ... . - , getty (pid ). - - init getty - ( - , - - ). 6.6. FIFO-. . - FIFO- (first in, first out), - . . - - , - .  "" read ( ) , - FIFO- - . - lseek() - -  FIFO-. FIFO- #include <sys/types.h> #include <sys/stat.h> mknod( ߔ, S_IFIFO | 0666, 0 ); 0666 - . FIFO- - . FIFO-  FIFO-, - -. - "" pipe. pipe: int conn[2]; pipe(conn); - PIPEFILE, pipe . , 1992-95 - 231 - UNIX mknod("PIPEFILE", S_IFIFO | 0600, 0); conn[0] = open("PIPEFILE", O_RDONLY); conn[1] = open("PIPEFILE", O_WRONLY); unlink("PIPEFILE"); fork : pipe(conn); fork(); conn[0]----<---- ----<-----conn[1] FIFO conn[1]---->---- ---->-----conn[0] A B A B. A : close(conn[0]); // .. write(conn[1], ... ); B close(conn[1]); // .. read (conn[0], ... ); : conn[1]---->----FIFO---->-----conn[0] A B , A conn[1] dup2 (conn[1], 1); close(conn[1]); write(1, ... ); /* printf */ B - conn[0] dup2(conn[0], 0); close(conn[0]); read(0, ... ); /* gets */ $ A | B . , pipe, ( ). - , - write, . , - . A B, B wait, conn[0]. A conn[1]. , : A , B , A; B - A , . B wait , ( EOF). close(conn[0]); . , 1992-95 - 232 - UNIX B wait. B close(conn[0]) , A , write A, A SIGPIPE - " , ". 6.6.1. FIFO (""), FIFO . open , - . , , , - ,  - ? O_NDELAY open. int fd = open(filename, O_RDONLY|O_NDELAY); open , (-1). - >=0, . O_NDELAY , . , , , . () , ( open ). , - , , "" open, close . - O_NDELAY. #include <stdio.h> #include <fcntl.h> /* O_NDELAY */ void nondelay(int fd){ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NDELAY); } int main(int ac, char *av[]){ int fd; char *port = ac > 1 ? "/dev/term/a" : "/dev/cua/a"; retry: if((fd = open(port, O_RDWR|O_NDELAY)) < 0){ perror(port); sleep(10); goto retry; } printf(" %s .\n", port); nondelay(fd); printf(" , !\n"); sleep(60); printf(".\n"); return 0; } : . , 1992-95 - 233 - UNIX su# a.out & a.out xxx [1] 22202 /dev/term/a . , ! /dev/cua/a: Device busy /dev/cua/a: Device busy /dev/cua/a: Device busy /dev/cua/a: Device busy /dev/cua/a: Device busy /dev/cua/a: Device busy . /dev/cua/a . , ! su# 6.7. .  . setjmp " "|-, longjmp ,   ( )|=. , - , , . , , : #include <signal.h> #include <setjmp.h> jmp_buf jmp; /* */ /* */ void onintr(nsig){ longjmp(jmp, nsig); } main(){ int n; n = setjmp(jmp); /* */ if( n ) printf( " %d\n", n); signal (SIGINT, onintr); /* */ printf("\n"); ... } setjmp 0  . longjmp, setjmp, - longjmp, - nsig. (backtracking): - - , - - - . : ( jmp_buf - ). ____________________ |- : (stack pointer); , (instruction pointer). |= . , - setjmp longjmp (.. ). . , 1992-95 - 234 - UNIX 6.7.1. longjmp. #define FOUND 1 /* */ #define NOTFOUND 0 /* */ int value; /* */ main(){ int i; for(i=2; i < 10; i++){ printf( " i=%d\n", i); if( test1(i) == FOUND ){ printf(" %d\n", value); break; } } } test1(i){ int j; for(j=1; j < 10 ; j++ ){ printf( " j=%d\n", j); if( test2(i,j) == FOUND ) return FOUND; /* "" return */ } return NOTFOUND; } test2(i, j){ printf( "(%d,%d)\n", i, j); if( i * j == 21 ){ printf( " (%d,%d)\n", i,j); value = j; return FOUND; } return NOTFOUND; } , return-: #include <setjmp.h> jmp_buf jmp; main(){ int i; if( i = setjmp(jmp)) /* */ printf(" %d\n", --i); else /* */ for(i=2; i < 10; i++) printf( " i=%d\n", i), test1(i); } test1(i){ int j; for(j=1; j < 10 ; j++ ) printf( " j=%d\n", j), test2(i,j); } test2(i, j){ printf( "(%d,%d)\n", i, j); if( i * j == 21 ){ printf( " (%d,%d)\n", i,j); longjmp(jmp, j + 1); } } , longjmp 1, . j==0, setjmp 0 (  - ). 6.7.2. ? #include <setjmp.h> . , 1992-95 - 235 - UNIX jmp_buf jmp; main(){ g(); longjmp(jmp,1); } g(){ printf(" g\n"); f(); printf(" g\n"); } f(){ static n; printf( " f\n"); setjmp(jmp); printf( " f %d- \n", ++n); } : longjmp f(), - . "" - "". "" , . : , , . - f() main() - , main() , f(). .. "" : f() main() g(); g() main(); -- -- | f | | g | | main | - ---------- : main() g() f(); g() f(). : f(){ ... A: setjmp(jmp); ... longjmp(jmp, ...); ... /* goto A; */ } 6.8. , , . UNIX - . , , ,  ( ).  , /etc/init. 6.8.1. - , - . UNIX : (user id), : , - . /etc/passwd. , - , passwd: . , 1992-95 - 236 - UNIX #include <stdio.h> #include <pwd.h> struct passwd *p; int uid; /* */ char *uname; /* . */ uid = getuid(); p = getpwuid( uid ); ... p = getpwnam( uname ); , - . : p->pw_uid . (int uid); p->pw_gid . ; char[] p->pw_name (uname); p->pw_dir (, ); p->pw_shell ( "", /bin/sh); p->pw_comment ( ); p->pw_gecos ( ); p->pw_passwd .  ! p==NULL, (- , uid). uid getuid, uid - st_uid , - stat ( - st_gid). : ls, . 6.8.2. chown(char *ߔ, int uid, int gid); .. "" . . S_ISUID S_ISGID (. ) , " " , , - ! 6.8.3. ( di_uid I- i_uid I- |-). ( u_uid u_ruid u-area). ,  , - . ruid " " , uid - " ". exec() , : ____________________ |- , -  I- ( , ). I- ,