天天看點

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

異常

異常是控制流中的突變,用來響應處理器狀态中的某些變化。

控制流:控制轉移序列。

控制轉移:從一條指令到下一條指令。

異常控制流:現代作業系統通過使控制流發生突變來對系統狀态做出反應,這些突變稱為異常控制流。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

1、處理程式将控制傳回給目前指令Icurr,即當事件發生時正在執行的指令。

2、處理程式将控制傳回給Inext,如果沒有發生異常将會執行的下一條指令。

3、處理程式終止被中斷的程式。

異常處理

異常表:當處理器檢測到有事件發生時,它會通過跳轉表,進行一個間接過程調用(異常),到異常處理程式。

異常号:系統中可能的某種類型的異常都配置設定了一個唯一的非負整數的異常号。異常号是到異常表中的索引。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

一旦硬體觸發了異常,異常處理程式則由軟體完成。

異常的類别

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

中斷處理:異步是指硬體中斷不是由任何一條指令造成的,而是由外部I/O裝置的事件造成的。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

陷阱和系統調用:系統調用是一些封裝好的函數,内部通過指令int n實作。

陷阱最重要的用途是提供系統調用。系統調用運作在核心模式中,并且可以通路核心中的棧。

系統調用的參數是通過通用寄存器而不是棧來傳遞的,如,%eax存儲系統調用号,%ebx,%ecx,%edx,%esi,%edi,%ebp最多存儲六個參數,%esp不能用,因為進入核心模式後,會覆寫掉它。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

故障處理:根據故障是否能夠被修複,故障處理程式要麼重新執行引起故障的指令,要麼終止。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

終止處理:是不可恢複的緻命錯誤造成的結果,通常是一些硬體錯誤。終止處理程式将控制傳遞給一個核心abort例程,該例程會終止這個應用程式。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

Linux系統調用示例:

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

程序

程序是一個執行中程式的執行個體。系統中每個程式都是運作在某個程序的上下文中的。上下文由程式正确運作所需的狀态組成,包括程式的存放在存儲器中的代碼和資料、棧、通用目的寄存器的内容、程式計數器、環境變量和打開檔案描述符的集合。

程序(作業系統層):邏輯控制流,私有位址空間,多任務,并發,并行,上下文,上下文切換,排程。

程序就是一個執行中的程式執行個體。系統中的每個程式都是運作在某個程序的上下文中的。

程序提供給應用程式的關鍵抽象:

a) 一個獨立的邏輯控制流 ;

b)一個私有的位址空間

邏輯控制流

程式計數器(PC)值的序列叫做邏輯控制流,簡稱邏輯流。如下圖所示,處理器的一個實體控制流分成了三個邏輯流,每個程序一個。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

并發流

并發流:并發流一個邏輯流的執行在時間上與另一個流重疊。

并發:多個流并發執行的一般現象稱為并發。

多任務:多個程序并發叫做多任務。

并行:并發流在不同的cpu或計算機上,叫并行。

練習題8.1

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

邏輯流在時間上和其他邏輯流重疊的程序稱為并發程序。

A,B和B,C執行時間上有重合,說明它們各自的執行是重疊的,是以是并發的。

A,C執行時間無重合,是以不是并發。

程序執行控制流的一部分的時間段稱為時間片,程序和其他程序輪換運作稱為多任務,也稱時間分片。

私有位址空間

一個程序為每個程式提供它自己的私有位址空間。

運作應用程式代碼的程序初始時是在使用者模式中的。程序從使用者模式變為核心模式的唯一方法是通過異常。

linux提供了/proc檔案系統,它允許使用者模式程序通路核心資料結構的内容。

程序為每個程式提供私有位址空間,和這個空間中某位址相關聯的存儲器位元組不能被其他程序讀寫。和私有位址空間關聯的存儲器内容一般不同,但空間有相同的結構。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

使用者模式和核心模式

需要限制一個應用可以執行的指令以及可通路的位址空間範圍來實作程序抽象,通過特定控制寄存器的一個模式位來提供這種機制。設定了模式位時,程序運作在核心模式中,程序可以執行任何指令和通路任何存儲器位置。沒設定模式位時,程序運作在使用者模式中,程序不允許執行特權指令和通路位址空間中核心區内的代碼和資料。使用者程式必須通過系統調用接口間接地通路核心代碼和資料。

使用者程式的程序初始是在使用者模式中的,必須通過中斷、故障或陷入系統調用這樣的異常來變為核心模式。

Linux有一種 /proc 檔案系統,包含核心資料結構的内容的可讀形式,運作使用者模式程序通路。

上下文切換

核心為每個程序維持一個上下文,它是核心重新啟動一個被搶占程序所需的狀态。包括通用目的寄存器、浮點寄存器、程式計數器、使用者棧、狀态寄存器、核心棧和各種核心資料結構(頁表、程序表和檔案表等)的值。

核心通過上下文切換來實作多任務,它是一種進階的異常控制流,建立在低級異常機制上。

核心決定搶占目前程序,重新開始一個先前被搶占的程序,稱為排程了一個新程序,由核心中的排程器代碼處理。使用上下文切換來将控制轉移到新程序。上下文切換儲存目前程序的上下文,恢複先前被搶占程序儲存的上下文,将控制傳遞給新恢複的程序。

系統調用和中斷可以引發上下文切換。

上下文切換:作業系統核心使用叫上下文切換的異常控制流來實作多任務。

上下文切換:

a) 儲存目前程序的上下文;

b) 恢複某個先前被搶占的程序被儲存的上下文;

c) 将控制傳遞給這個新恢複的程序。

排程:核心中的排程器實作排程。

當核心代表使用者執行上下文切換時,可能會發生上下文切換。如果系統調用發生阻塞,那麼核心可以讓目前程序休眠,切換到另一個程序,如read系統調用,或者sleep會顯示地請求讓調用程序休眠。一般,即使系統調用沒有阻塞,核心亦可以決定上下文切換,而不是将控制傳回給調用程序。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

系統調用錯誤處理

在Linux中,可以使用 man syscalls 檢視全部系統調用的清單。系統級函數遇到錯誤時,通常傳回-1,并設定全局變量 errno。

strace 指令可以列印程式和它的子程序調用的每個系統調用的軌迹。

程序控制

程序有三種狀态:

運作:程序在CPU上執行,或等待被執行(會被排程)。

停止:程序被挂起(不會被排程)。收到 SIGSTOP 、 SIGTSTP 、 SIDTTIN 、 SIGTTOU 信号,程序停止,收到 SIGCONT 信号,程序再次開始運作。

終止:程序永遠停止。原因可能是:收到終止程序的信号,從主程式傳回,調用 exit 函數。

建立新程序可以使用 fork 函數。新建立的子程序和父程序幾乎相同,它獲得父程序使用者級虛拟位址空間和檔案描述符的副本,主要差別是它們的PID不同。 fork 函數調用一次,傳回兩次;父子程序是并發運作的,不能假設它們的執行順序;兩個程序的初始位址空間相同,但是是互相獨立的;它們還共享打開的檔案。

練習題8.2

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

子程序輸出:

P1:x=2

P2:x=1

父程序輸出:

P2:x=0

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

程序終止時,并不會被立即清除,而是等待父程序回收,稱為僵死程序。父程序回收終止的子程序時,核心将子程序退出狀态傳給父程序,然後抛棄該程序。如果回收前父程序已經終止,那麼僵死程序由 init 程序回收。

回收子程序可以用 wait 和 waitpid 等函數。

練習題8.3

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

輸出序列為:bacc acbc abcc

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

核心調用 execve 函數在目前程序的上下文中加載并運作一個新程式。 execve 加載 filename 後,調用啟動代碼,啟動代碼準備棧,将控制傳給新程式的主函數 int main(int argc, char *argv[], char *envp[])。

練習題8.4

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

輸出6行

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

參數數組和環境數組會被傳遞給程式。按C标準, main 函數隻有兩個參數,一般環境數組使用全局變量environ 傳遞。

練習題8.5

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

操作環境數組可以通過 getenv 函數族。

程式是代碼和資料的集合,可以作為目标子產品存在于磁盤,或作為段存在于位址空間中。程序是執行中程式的一個執行個體。程式總是運作在某個程序的上下文中。

ps 指令可以檢視系統中目前的程序。

top 指令會列印目前程序資源使用的資訊。

練習題8.6

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

信号

信号是一種更高層軟體形式的異常,它允許程序中斷其他程序。一個信号即一條資訊,通知程序一個某種類型的事件已經在系統中發生了。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

每種信号類型都對應某個類型的系統事件。底層硬體異常通常對使用者程序不可見,信号提供了一種機制向使用者程序通知這些異常的發生。其他信号對應核心或其他使用者程序中較高層的軟體事件。

發送信号指核心通過更新目的程序上下文中的某個狀态,發送一個信号給目的程序。發送信号的原因有:

1、 核心檢測到一個系統事件,如除零或子程序終止。

2、程序調用了 kill 函數,顯示要求核心發送信号給目的程序。程序可以給自己發送信号。

接收信号指目的程序被核心強迫以某種方式對信号的發送做出反應。程序可以忽略信号,終止,或執行信号處理程式捕獲信号。

發出而沒有被接收的信号稱為待處理信号。一種類型最多有一個待處理信号,重複的信号被丢棄。程序可以阻塞某種信号,這時仍可被發送,但不會被接收。一個待處理信号最多隻能被接收一次。

發送信号

發送信号給程序基于程序組的概念。程序組由一個正整數ID辨別,每個程序隻屬于一個程序組。

shell為每個作業建立一個獨立的程序組,程序組ID一般為作業中父程序中的一個。

^C 發送 SIGINT 信号到shell,shell捕獲信号發送給前台程序組的每個程序,預設終止前台作業。 ^Z 發送SIGTSTP 信号到shell,shell捕獲信号發送給前台程序組的每個程序,預設挂起前台作業。

用 kill 指令向其他程序發送任意信号,給定的PID為負值時,表示發送信号給程序組ID為PID絕對值的所有程序。

程序可以用 kill 函數發送信号給任意程序(包括自己)。

接受信号

每個程序都有一個信号屏蔽字,它規定了目前要阻塞遞送到該程序的信号集。每個可能的信号都有一位屏蔽字,對應位設定時表明信号目前是被阻塞的。用 sigprocmask 函數檢測和更改目前信号屏蔽字。

每個信号類型都有一個預定義的預設行為,為下面中的一種:

1、 程序終止。

2、 程序終止并轉儲記憶體。

3、 程序停止(挂起)直到被SIGCONT信号重新開機。

4、 程序忽略該信号。

核心從異常處理程式傳回,将控制傳遞給程序p之前會檢查未被阻塞的待處理信号的集合。集合為空則核心傳遞控制給程序p的邏輯控制流的下一條指令;集合非空則核心選擇集合中某個信号k(通常取最小k),強制程序p接收k。信号觸發程序的某種行為,程序完成行為後控制傳遞給p的邏輯控制流的下一條指令。

每種信号都有預設行為,可以用 signal 函數修改和信号關聯的預設行為(除 SIGSTOP 和 SIGKILL 外):

#include <signal.h>

typedef void (*sighandler_t)(int);

/** 改變和信号signum關聯的行為
 * @return      傳回前次處理程式的指針,出錯傳回SIG_ERR */
sighandler_t signal(int signum, sighandler_t handler);

           

指向使用者定義函數,也就是信号處理程式的指針。或者為:

SIG_IGN :忽略 signum 信号。

SIG_DFL :恢複 signum 信号預設行為。

信号處理程式的調用稱為捕捉信号,信号處理程式的執行稱為處理信号。 signal 函數會将 signum 參數傳遞給信号處理程式 handler 的參數,這樣 handler 可以捕捉不同類型的信号。

signal 的語義和實作有關,最好使用 sigaction 函數代替它。

信号處理程式可以被其他信号處理程式中斷。

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

練習題8.7

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
#include<csapp.h>

void handler(int sig)
{
    return;
}

unsigned int snooze(unsigned int secs)
{
    unsigned int rc=sleep(secs);
    printf("Slept for %d of %d secs.\n",secs-rc,secs);
    return rc;
}

int main(int argc,char **argv[])
{
    if(argc!=2)
    {
        fprintf(stderr,"usage:%s <secs>\n",argv[0]);
        exit(0);
    }
    if(signal(SIGINT,handler)==SIG_ERR)
        unix_error("signal error\n");
    (void)snooze(atoi(argv[1]));
    exit(0);
}

           

信号處理

不會有重複的信号排隊等待。信号處理有以下特性:

信号處理程式阻塞目前正在處理的類型的待處理信号。

同種類型至多有一個待處理信号。

會潛在阻塞程序的慢速系統調用被信号中斷後,在信号處理程式傳回時不再繼續,而傳回一個錯誤條件,并将 errno 設為 EINTR 。

對于第三點,Linux系統會重新開機系統調用,而Solaris不會。不同系統之間,信号處理語義存在差異。Posix标準定義了 sigaction 函數,使在Posix相容的系統上可以設定信号處理語義。

練習題8.8

下面這個程式輸出什麼?

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

父程序開始時列印“2”,然後建立子程序,子程序會陷入一個無限循環。然後父程序向子程序發送一個信号,并等待它終止。子程序捕獲這個信号(中斷這個無限循環),對計數器值(從初始值2)減1,列印“1”,然後終止。在父程序回收子程序之後,它對計數器值(從初始值2)加1,列印“3”,并且終止。

非本地跳轉

C提供了一種使用者級的異常控制流,稱為非本地跳轉。它将控制直接從一個函數轉移到另一個正在執行的函數,而不需要經過正常的調用-傳回序列。

非本地跳轉通過setjmp和longjmp函數來提供。

非本地跳轉可以用來從一個深層嵌套的函數調用中立即傳回,如檢測到錯誤;或者使一個信号處理程式轉移到一個特殊的代碼位置,而不是傳回到信号中斷的指令的位置。

在信号處理程式中進行非本地跳轉時應使用 sigsetjmp 和 siglongjmp 。如果 savesigs 非0,則 sigsetjmp 在 env 中儲存程序的目前信号屏蔽字,調用 siglongjmp 時從 env 恢複儲存的信号屏蔽字。同時,應該使用一個 volatile sig_atomic_t 類型的變量來確定 env 未設定時不被中斷。

舉例:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

static sigjmp_buf               buf;
static volatile sig_atomic_t    canjmp;

void handler(int sig)
{
    if (canjmp == 0)
        return;
    /* ... */
    canjmp = 0;
    siglongjmp(buf, 1);
}

int main()
{
    signal(SIGINT, handler);
    if (!sigsetjmp(buf, 1))
        printf("starting\n");
    else
        printf("restarting\n");
    canjmp = 1;
    while (1) {
        sleep(1);
        printf("processing ...\n");
    }
    exit(0);
}
           
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

家庭作業

8.9

考慮四個具有如下開始和結束時間的程序

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

對于每個程序,指明他們是否并發運作

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

8.10

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

A. 調用一次,傳回兩次: fork

B. 調用一次,從不傳回: execve, longjmp

C. 調用一次,傳回一次或者多次: setjmp

8.11

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

父程序列印一次,子程序運作兩次,列印兩行,父程序再運作一次,共4行。

8.12

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

8行。

8.13

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

423或243

8.14

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

主程序隻列印一行。

主程序的直接子程序會列印一行,子程序的子程序又列印一行。

是以是3行。

8.15

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

這裡的子程序不是exit,而是return,說明兩個子程序都要到回到main函數去列印那裡的hello。是以是5行。

8.16

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

輸出counter = 2,因為全局變量也是複制的,而不是共享的。

8.17

Hello 1 Bye 0 2 Bye

Hello 1 0 Bye 2 Bye

Hello 0 1 Bye 2 Bye

8.18

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

程序如圖:

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

A C E

8.19

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

2^n行

8.20

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
int main(int argc, char* args[])
{
    execve("/bin/ls", args, environ); //沒有錯誤處理,注意環境變量
    return 0;
}
           

8.21

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

abc或bac。

8.22

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
int mysystem(char *command)
{
    int status;
    char *argv[4];
    char *a0 = "sh";
    char *a1 = "-c";
    if( fork()==0 ) /*子程序*/
    { 
        argv[0] = a0;
        argv[1] = a1;
        argv[2] = command;
        argv[3] = NULL;
        execve("/bin/sh", args, environ);
        return -1; //執行異常
    }
    else{ /*父程序*/
        if( wait(&status) > 0)
        {
            if(WIFEXITED(status) != 0)
                return WEXITSTATUS(status);
            else return status;
        }
        else return -1; //wait異常
    }
}
           

8.23

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

一個可能的原因是,在第一個信号發給父程序之後,父程序進入handler,并且阻塞了SIGUSR2,第二個信号依然可以發送,然而,之後的3個信号便會被抛棄了。因為是連續發送,是以很可能是沒等上下文切換,這5個信号就同時發送了。是以隻有2個信号被接收。

8.24

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
#include "csapp.h"
#define N 2

int main()
{
    int status, i;
    pid_t pid;
    char errorInfo[128];
    /* Parent creates N children */
    for(i=0;i<N;i++)
        if ((pid = Fork()) == 0) /* Child */
            exit(100+i);

    while ((pid = waitpid(-1, &status, 0)) > 0) {
        if (WIFEXITED(status))
            printf("child %d terminated normally with exit status=%d\n",
                    pid, WEXITSTATUS(status));
        else if(WIFSIGNALED(status))
        {
            printf("child %d terminated by signal %d: ", 
                pid, WTERMSIG(status) );
            psignal(WTERMSIG(status), errorInfo); //psignal會列印sig的資訊
        }
    }
    if (errno != ECHILD)
        unix_error("waitpid error");
    exit(0);
}
           

8.25

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
sigjmp_buf env;
void tfgets_handler(int sig)
{
    signal(SIGALRM, SIG_DFL);
    siglongjmp(env, 1);
}

char *tfgets(char *buf, int bufsize, FILE *stream)
{
    static const int TimeLimitSecs = 5;
    signal(SIGALRM, tfgets_handler)
    alarm(TimeLimitSecs);
    int rc = sigsetjmp(env, 1);
    if(rc == 0) return fgets(buf, bufsize, stream);
    else return NULL; //alarm,time out
}
           

8.26

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

未完成。

教材學習中的問題和解決過程

  • 問題1:

練習題8.5輸出的結果與預期結果不一樣

  • 問題1解決方案:

頭檔案的使用錯誤,應使用csapp.h頭檔案。

代碼調試中的問題和解決過程

帶有csapp.h頭檔案的程式無法被執行

linux沒有自帶csapp.h,是以要自己導入,将csapp.h要放到 /usr/include的檔案夾裡面。打開後這裡面有好多頭檔案

要在頭檔案的#end if前面加上一句#include <csapp.c>,因為那個頭檔案要把csapp.c檔案包含進去 這樣的話就可以用了。

代碼托管

2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結

結對及互評

本周結對學習情況

- [20155214](http://www.cnblogs.com/besti155214/p/8052476.html)

- 結對照片
           
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
- 結對學習内容
           

解答同伴問題:

  • 1、在程式中如何異步回收子程序?
  • 解答:

當一個程序fork出子程序後,沒有對子程序進行回收,那麼子程序運作完之後的狀态會變為僵屍程序.

我們可以通過wait和waitpid來回收子程序,防止僵屍程序的出現.

但是wait和waitpid,要麼以阻塞方式運作,要麼以輪詢方式運作,都極大的占用了CPU資源.

在每個子程序運作完成之後,都會向父程序發出SIGCHLD信号.而在預設情況下,父程序會忽略掉該信号.是以,我們隻需要對SIGCHLD信号進行捕捉,即可異步對子程序進行回收.

一下是一個示例代碼:

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdlib.h>
void waitChild1(int sig){
    int status = 0;
    if(waitpid(-1,&status,WNOHANG)>0){
        printf("the child exit status is %d\n",WEXITSTATUS(status));
    }else{
        printf("failure!\n");
    }
}
void waitChild2(int sig){
    int status = 0;
    pid_t pid = 0;
    while((pid = waitpid(-1,&status,WNOHANG)) >0){
        printf("%d's exit status is %d\n",pid,WEXITSTATUS(status));
    }
}
int main(){
    signal(SIGCHLD,waitChild2);
    int pid = fork();
    if(pid == 0){
        //child
        printf("i am child,my pid is %d\n",getpid());
        exit(1);
    }
    pid = fork();
    if(pid == 0){
        //child
        printf("i am child,my pid is %d\n",getpid());
        exit(1);
    }
    pid = fork();
    if(pid == 0){
        //child
        printf("i am child,my pid is %d\n",getpid());
        exit(1);
    }
    pid = fork();
    if(pid == 0){
        //child
        printf("i am child,my pid is %d\n",getpid());
        exit(1);
    }
    while(1){
        printf("i am father,my pid is %d\n",getpid());
        sleep(5);
    }
    return 0;
}
           
2017-2018-1 20155216 《資訊安全系統設計基礎》第十三周學習總結
  • 2、如何使用非本地跳轉來規避正常的調用/傳回棧規則。
#include <setjmp.h>

/** 在env緩沖區中儲存目前棧的内容,供longjmp使用,傳回0
 * @return      setjmp傳回0,longjmp傳回非0 */
int setjmp(jmp_buf env);
int sigsetjmp(sigjmp_buf env, int savesigs);
/** 從env緩沖區中恢複棧的内容,觸發一個從最近一次初始化env的setjmp調用的傳回,setjmp傳回非0的給定val值 */
void longjmp(jmp_buf env, int val);
void siglongjmp(sigjmp_buf env, int val);
           

其他(感悟、思考等,可選)

1、深入學習了程序的相關概念。

學習進度條

代碼行數(新增/累積) 部落格量(新增/累積) 學習時間(新增/累積) 重要成長
目标 5000行 30篇 400小時
第三周 114/114 3/3 20/20
第四周 136/250 2/5 18/38
第五周 87/337 2/7 22/60
第六周 271/608 2/9 30/90
第七周 185/716 2/11
第八周 531/1247 3/14
第九周 439/1686 3/17
第十一周 153/1839 2/19
第十三周 628/2467 2/21

嘗試一下記錄「計劃學習時間」和「實際學習時間」,到期末看看能不能改進自己的計劃能力。這個工作學習中很重要,也很有用。

耗時估計的公式

:Y=X+X/N ,Y=X-X/N,訓練次數多了,X、Y就接近了。

參考:軟體工程軟體的估計為什麼這麼難,軟體工程 估計方法

  • 計劃學習時間:25小時
  • 實際學習時間:20小時
  • 改進情況:

(有空多看看現代軟體工程 課件

軟體工程師能力自我評價表)

參考資料

  • 《深入了解計算機系統V3》學習指導
  • ...