/* * Fatal error related to a system call. * Print a message and terminate. */ void err_sys(const char *fmt, ...) { va_list ap; va_start(ap, fmt); err_doit(1, errno, fmt, ap); va_end(ap); exit(1); } /* * Print a message and return to caller. * Caller specifies "errnoflag". */ static void err_doit(int errnoflag, int error, const char *fmt, va_list ap) { char buf[MAXLINE]; vsnprintf(buf, MAXLINE-1, fmt, ap); if (errnoflag) snprintf(buf+strlen(buf), MAXLINE-strlen(buf)-1, ": %s", strerror(error)); strcat(buf, "\n"); fflush(stdout); /* in case stdout and stderr are the same */ fputs(buf, stderr); fflush(NULL); /* flushes all stdio output streams */ }
#include "myapue.h" int globvar = 6; char buf[] = "a write to stdout\n"; int main(void) { int var; pid_t pid; var = 88; if(write(STDOUT_FILENO, buf, sizeof(buf) - 1) != sizeof(buf) - 1) err_sys("write error"); printf("before fork\n"); if((pid = fork()) < 0){ err_sys("fork error"); }else if(pid == 0){ globvar++; var++; }else sleep(2); printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var); exit(0); }
(1)<7>函數
STDIN_FILENO、STDOUT_FILENO:<unistd.h>,指定標準輸入和標準輸出的文件描述符。code
(2)<184>進程
由於緩衝區buf已經用已知字符串初始化,其長度是固定的,因此sizeof是在編譯時計算緩衝區長度。ci
(3)字符串
write函數不帶緩衝,get
printf函數帶緩衝(標準IO庫)it
若是標準輸出鏈接到終端設備,則它是行緩衝;不然它是全緩衝的(此處在進程終止時,其緩衝區中的內容寫到相應文件中)。io
#include "myapue.h" int globvar = 6; int main(void) { int var; pid_t pid; var = 88; printf("before vfork\n"); if((pid = vfork()) < 0) err_sys("vfork error"); else if(pid == 0){ globvar++; var++; _exit(0); } printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar, var); exit(0); }
(1)<187>編譯
vfork函數:class
一、它不將父進程的地址空間徹底複製到子進程。子進程應當即調用exec或exit函數,不然它在父進程的空間運行,可能會帶來未知的結果。
二、vfork保證子進程先運行,在它調用exec或exit以後父進程才能被調度運行。
(2)<159>
_exit函數:正常終止程序,並當即進入內核,不執行清理處理。
#include "myapue.h" int main(void) { pid_t pid; if((pid = fork()) < 0) err_sys("fork error"); else if(pid == 0){ if((pid = fork()) < 0) err_sys("fork error"); else if(pid > 0)//first child exit(0); //second child sleep(2); printf("second child, parent pid = %ld\n", (long)getppid()); exit(0); } //parent if(waitpid(pid, NULL, 0) != pid) err_sys("waitpid error"); exit(0); }
(1)<190>
fork函數:子進程的返回值是0,父進程的返回值是新建子進程的進程ID。
waitpid函數:第一個參數爲pid,pid>0:等待進程ID與pid相等的子進程。成功則返回終止進程的進程ID。
(2)調用兩次fork,則父進程不用等待子進程終止,子進程也不用處於僵死狀態直到父進程終止,由於父進程的子進程已經終止了。這樣把子進程的任務交給子進程的子進程去作,兩個任務互不影響。