APUE學習筆記-fork、vfork、fork2次

/*
 * 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_FILENOSTDOUT_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

    一、它不將父進程的地址空間徹底複製到子進程。子進程應當即調用execexit函數,不然它在父進程的空間運行,可能會帶來未知的結果。

    二、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,則父進程不用等待子進程終止,子進程也不用處於僵死狀態直到父進程終止,由於父進程的子進程已經終止了。這樣把子進程的任務交給子進程的子進程去作,兩個任務互不影響。

相關文章
相關標籤/搜索