1. 程式人生 > >exit()與wait-()函式

exit()與wait-()函式

exit()與wait*()函式

標籤(空格分隔):程序控制


這節的知識我就基本只是把書上的整理了一下, 僅僅只是個人覺得有用的整理了下。

exit()函式

  • _Exit() : 其目的是為程序提供一種無需執行終止處理程式或訊號處理程式而終止的方法
  • _exit() : _exit()由exit()呼叫,處理UNIX特定的細節
  • 最後一個程序呼叫return等其他終止的返回值並不作為程序的返回值. 當最後一個程序從啟動例程返回時, 該程序以終止狀態0返回.
  • 終止
    | |
    | :----- |
    | 不管程序是怎麼終止的, 最後都會呼叫核心的同一段程式碼. 這段程式碼會關閉所有的流操作, 釋放所使用的儲存器.
    |
    | 在異常終止時, 系統會返回一個異常終止狀態.|
    | 父程序通過wait()watipid()函式來獲得終止狀態.|
    | 在最後呼叫exit()時, 轉化為終止狀態 |
    | 在父程序比子程序先終止時,父程序會改變為init程序(也是之前說的init會成為所有孤程序的父程序(原因 :在程序終止時, 核心逐個檢查所有活動的程序, 以判斷是不是正要終止程序的子程序, 如果是, 則該程序的父程序ID改為1.)|
    | 由init收養的父程序是不會變為殭屍程序的(殭屍程序 : 一個已終止, 但是其父程序沒有對其做善後處理) |

wait()函式

wait()

  1. pid_t wait(int *statloc)
  • 子程序執行時, wait使呼叫者堵塞
  • statloc != NULL 則程序的終止狀態就存放在其所指的單元, statloc == NULL 則不關心其終止狀態
  • 當一個子程序終止就立刻返回。

waitpid()

  1. pid_t waitpid(pid_t pid, int *statloc, int options)
  • 可以並不堵塞
  • 可以等待pid指定的程序終止在執行waitpid()的呼叫者。
  • statloc != NULL 則程序的終止狀態就存放在其所指的單元, statloc == NULL 則不關心其終止狀態
  • pid的值
    pid == -1 等待任意子程序
    pid > 0 等待 “程序ID == pid” 的程序
    pid == 0 等待 ”組ID == 呼叫程序組ID”的任意程序
    pid < -1 等待 “組ID == |pid|“ 的程序

如果一個程序fork一個子程序, 但是想等待子程序終止再進行, 也不希望子程序處於殭屍狀態直到父程序終止, 這就需要呼叫兩次fork() (通俗一點就是希望父程序在子程序之前終止)

/*************************************************************************
    > File Name: fork_wait_子程序.cpp
    > Author: Function_Dou
    > Mail: 
    > Created Time: 2018年01月30日 星期二 11時23分27秒

	
	pid_t waitpid(pid_t pid, int *statloc, int options)
	
	可以並不堵塞
	可以等待pid指定的程序終止在執行waitpid()的呼叫者。
	statloc != NULL 則程序的終止狀態就存放在其所指的單元, statloc == NULL 則不關心其終止狀態
	
	pid的值
	
	pid == -1 等待任意子程序
	pid > 0 等待 “程序ID == pid” 的程序
	pid == 0 等待 ”組ID == 呼叫程序組ID”的任意程序
	pid < -1 等待 “組ID == |pid|“ 的程序

 ************************************************************************/

#include <stdio.h>
#include "apue.h"
#include <sys/wait.h>

int main(void)
{
	// pid_t pid = -1;
	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)
			exit(0);

		sleep(2);
		printf("second child, parent pid = %ld\n", (long)getppid());
		exit(0);
	}

	if(waitpid(pid, NULL, 0) != pid)
		err_sys("waitpid error");

	exit(0);
}

/*          樣例
[[email protected] Process]# ./a.out 
[[email protected] Process]# second child, parent pid = 1

[[email protected] Process]# 
*/

巨集 說明
WIFEXITED 正常終止(真)可執行WEXITSTATUS 來獲取子程序傳遞給exit, _exit引數
WIFSIGNALED 異常終止(真)可執行WTERMSIG 獲取子程序終止的訊號編號
WIFSTOPPED 暫停子程序的返回的狀態(真)WSTOPSIG 獲取子程序暫停的訊號編號
/*************************************************************************
    > File Name: exit__退出狀態.cpp
    > Author: Function_Dou
    > Mail: 
    > Created Time: 2018年01月31日 星期三 21時40分13秒
 ************************************************************************/

#include <stdio.h>
#include "apue.h"
#include <sys/wait.h>

void pr_exit(int status)
{
    // 正常終止
	if(WIFEXITED(status))
		printf("normal termination, exit status = %d\n", WEXITSTATUS(status));
	// 異常終止
	else if(WIFSIGNALED(status))
		printf("abnormal termination, signal number = %d%s\n", WTERMSIG(status), 
#ifdef WCOREDUMP
		WCOREDUMP(status) ? " (core file generated)" : "");
#else
		"");
#endif
    // 暫停子程序
	else if(WIFSTOPPED(status))
		printf("child stopped, signal number = %d", WSTOPSIG(status));

}


int main(void)
{
	pid_t pid;
	int status;

    // 1
	if((pid = fork()) < 0)
		err_sys("fork error");
	else if(pid == 0)
		exit(7);

	if(wait(&status) != pid)
		err_sys("wait error");
	pr_exit(status);

    // 2
	if((pid = fork()) < 0)
		err_sys("fork error");
	else if(pid == 0)
		abort();
	
	if(wait(&status) != pid)
		err_sys("wait error");
	pr_exit(status);

    // 3
	if((pid = fork()) < 0)
		err_sys("fork error");
	else if(pid == 0)
		status /= 0;

	if(wait(&status) != pid)
		err_sys("wait error");
	pr_exit(status);


	exit(0);
}

/*      樣例
 ./a.out 
normal termination, exit status = 7
abnormal termination, signal number = 6 (core file generated)
abnormal termination, signal number = 8 (core file generated)
*/ 

競爭條件

競爭條件 : 當多個程序對共享資料進行某種處理, 但是最後結果又得取決於程序執行的順序。(通俗一點就是執行還得看系統的排程順序)

輪詢:等待父程序終止在進行子程序。(消耗cpu資源)

while(getppid != 1)
    sleep(1);

競爭條件的程式

/*************************************************************************
    > File Name: TELL_WAIT_競爭條件.cpp
    > Author: Function_Dou
    > Mail: 
    > Created Time: 2018年01月31日 星期三 22時38分46秒


	int putc(int ch, FILE *stream);
	引數ch表示要輸入的位置,引數stream為要輸入的流。
	若正確,返回輸入的的字元,否則返回EOF。

 ************************************************************************/

#include <stdio.h>
#include "apue.h"

static void charatatime(char *);

int main(void)
{
	pid_t pid;

	// 修改方法2
	// TELL_WAIT();

	// 修改方法1 
	// if((pid = vfork()) < 0)  沒有競爭關係了, 因為先進行子程序
	if((pid = fork()) < 0)
		err_sys("fork error");
	else if(pid == 0)
	{
		// 修改方法2
		// WAIT_PARENT();
		charatatime("one chile\n");
	}
	else
	{
		// 修改方法2
		// TELL_CHILD(pid);
		charatatime("first parent\n");
	}



	exit(0);
}

static void charatatime (char *str)
{
	char *ptr;
	int c;

	setbuf(stdout, NULL);
	for(ptr = str; (c = *ptr++) != NULL; )
		putc(c, stdout);

}


/*          樣例
[[email protected] Process]# ./a.out 
first oparent
ne chile
[[email protected] Process]# ./a.out 
first paronent
e chile
[[email protected] Process]# ./a.out 
first parenot
ne chile
*/

每次的結果不一樣, 因為這個要跟此時的程序順序有關。
書上的修改方法2執行有問題, 因為那些函式沒有包含進去, 所以無法測試。