亚洲视频二区_亚洲欧洲日本天天堂在线观看_日韩一区二区在线观看_中文字幕不卡一区

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.430618.com 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

導(dǎo)語(yǔ):這是篇讀書(shū)筆記,每次重讀CSApp都有新的認(rèn)知,尤其是在進(jìn)入了后臺(tái)通道之后才感受到每天和進(jìn)程打交道的感覺(jué)是如此深刻。
深入理解計(jì)算機(jī)系統(tǒng):進(jìn)程

 

0x00 What is Process?

深入理解計(jì)算機(jī)系統(tǒng):進(jìn)程

[ system structure ]

 

  • 進(jìn)程(Process)

經(jīng)典定義是一個(gè)執(zhí)行中的程序的實(shí)例,操作系統(tǒng)對(duì)一個(gè)正在運(yùn)行的程序的一種抽象。并發(fā)運(yùn)行,指的是一個(gè)進(jìn)程的指令和另一個(gè)進(jìn)程的指令交錯(cuò)執(zhí)行。操作系統(tǒng)實(shí)現(xiàn)這種交錯(cuò)執(zhí)行的機(jī)制稱(chēng)為上下文切換。

 

  • 線程(Thread)

一個(gè)進(jìn)程可以由多個(gè)線程的執(zhí)行單元組成,每個(gè)線程都運(yùn)行在進(jìn)程的上下文中,并共享同樣的代碼和全局?jǐn)?shù)據(jù)。

 

  • 內(nèi)核(Kernel)

一個(gè)計(jì)算機(jī)程序,用來(lái)管理軟件發(fā)出的數(shù)據(jù)I/O(輸入與輸出)要求,將這些要求轉(zhuǎn)譯為數(shù)據(jù)處理的指令,交由中央處理器(CPU)及計(jì)算機(jī)中其他電子組件進(jìn)行處理,是現(xiàn)代操作系統(tǒng)中最基本的部分。

 

  • 外殼(Shell)

指“為使用者提供使用者界面”的軟件,通常指的是命令行界面的解析器。一般來(lái)說(shuō),這個(gè)詞是指操作系統(tǒng)中提供存取內(nèi)核所提供之服務(wù)的程式。Shell也用于泛指所有為用戶提供操作界面的程序,也就是程序和用戶交互的層面。內(nèi)核不提供交互。

 

  • 搶占(Preemption)

分為非搶占式和搶占式。根據(jù)調(diào)度主體分用戶搶占與內(nèi)核搶占。

非搶占式(Nonpreemptive)——讓進(jìn)程運(yùn)行直到結(jié)束或阻塞的調(diào)度方式。

搶占式(Preemptive)——允許將邏輯上可繼續(xù)運(yùn)行的在運(yùn)行過(guò)程暫停的調(diào)度方式。可防止單一進(jìn)程長(zhǎng)時(shí)間獨(dú)占CPU。

 

  • 異常控制流(ECF,Exceptional Control Flow)

ECF發(fā)生在硬件層,操作系統(tǒng)層,應(yīng)用層。控制轉(zhuǎn)移(control transfer)是指程序計(jì)數(shù)器對(duì)應(yīng)的指令序列的跳轉(zhuǎn),控制轉(zhuǎn)移序列的叫做處理器的控制流(control flow)。

某些如跳轉(zhuǎn)、調(diào)用和返回是為了使得程序?qū)?nèi)部狀態(tài)變化(event)做出反應(yīng)而設(shè)計(jì)的機(jī)制,系統(tǒng)通過(guò)使控制流發(fā)生突變對(duì)發(fā)生各種狀態(tài)變化。

Exceptions

任何情況下,處理器檢測(cè)到event發(fā)生,通過(guò)異常表(exception table)跳轉(zhuǎn)到專(zhuān)門(mén)處理這類(lèi)事件的操作系統(tǒng)子程序(exception handler)。

異步異常由事件產(chǎn)生,同步異常是執(zhí)行一條指令的直接產(chǎn)物。

類(lèi)別包含中斷(異步)陷阱(同步)故障(同步)終止(同步)

  • 中斷——異步發(fā)生,處理器IO設(shè)備信號(hào)的結(jié)果。
  • 陷阱——有意的異常。最重要的用途是在用戶程序和內(nèi)核之間提供一個(gè)像過(guò)程一樣的接口,叫做系統(tǒng)調(diào)用。
  • 故障——潛在可恢復(fù)的錯(cuò)誤造成的結(jié)果。如果能被修復(fù),則重新執(zhí)行引起故障的指令,否則終止。
  • 終止——不可恢復(fù)的致命錯(cuò)誤造成的結(jié)果。

 

有高達(dá)256種不同的異常類(lèi)型,如出發(fā)錯(cuò)誤(0)、一般保護(hù)故障(13)、缺頁(yè)(14)、機(jī)器檢查(18)、操作系統(tǒng)定義的異常(32-127,129-255)、系統(tǒng)調(diào)用(0x80)。

 

我們常見(jiàn)的段故障(Segmentation fault),是一般保護(hù)故障(異常13),通常是因?yàn)橐粋€(gè)程序引用了一個(gè)未定義的虛擬存儲(chǔ)器區(qū)域,或者因?yàn)槌绦蛟噲D寫(xiě)一個(gè)只讀的文本段。

深入理解計(jì)算機(jī)系統(tǒng):進(jìn)程

[ Examples of popular system calls ]

Processes

  • 邏輯控制流(Logical Control Flow)

程序計(jì)數(shù)器PC值的序列叫做邏輯控制流(邏輯流)。PC對(duì)應(yīng)于程序的可執(zhí)行目標(biāo)文件中的指令,或者是包含在運(yùn)行時(shí)動(dòng)態(tài)鏈接到程序的共享對(duì)象中的指令。

邏輯流看起來(lái)就像是在獨(dú)占處理器地執(zhí)行程序,每個(gè)進(jìn)程執(zhí)行邏輯流的一部分然后就被搶占,實(shí)際上處理器通過(guò)上下文保護(hù)好進(jìn)程間的信息,在不同的進(jìn)程中切換。

 

  • 并發(fā)流(Concurrent Flows)

并發(fā)流指邏輯流在執(zhí)行時(shí)間上與另一個(gè)流重疊,多個(gè)就叫并發(fā)(concurrent)。

一個(gè)進(jìn)程和其他進(jìn)程輪流運(yùn)行叫多任務(wù)(multitasking)。

進(jìn)程占有CPU執(zhí)行控制流的每一個(gè)時(shí)間段叫時(shí)間片(time slice)。

多任務(wù)也叫做時(shí)間分片(time slicing)。

如果兩個(gè)流并發(fā)運(yùn)行在不同的處理器或者計(jì)算機(jī),稱(chēng)為并行流(parallel flow)。

 

  • 私有地址空間(Private Address Space)

一般,進(jìn)程間地址空間讀寫(xiě)保護(hù)。進(jìn)程地址空間32位進(jìn)程,代碼段從0x08048000開(kāi)始,64位進(jìn)程從0x00400000開(kāi)始:

深入理解計(jì)算機(jī)系統(tǒng):進(jìn)程

[ Process address space ]

  • 用戶模式和內(nèi)核模式(User and Kernel Modes)
  • 通過(guò)控制寄存器中的模式位(mode bit)描述進(jìn)程當(dāng)前享有的特權(quán)。
  • 內(nèi)核模式:(超級(jí)用戶)可執(zhí)行指令集中任何指令,并且可以訪問(wèn)系統(tǒng)中任何存儲(chǔ)器位置。
  • 用戶模式:不允許執(zhí)行特權(quán)指令,不允許直接引用地址空間中內(nèi)核區(qū)內(nèi)的代碼和數(shù)據(jù),任何嘗試都會(huì)引發(fā)致命保護(hù)故障。可以通過(guò)系統(tǒng)調(diào)用接口間接訪問(wèn)內(nèi)核代碼和數(shù)據(jù)。
  • 上下文切換(Context Switches)
  • 內(nèi)核為每個(gè)進(jìn)程維持一個(gè)上下文(context),是內(nèi)核重新啟動(dòng)一個(gè)被搶占的進(jìn)程所需的狀態(tài)。包括:
  • 通用目的的寄存器、浮點(diǎn)寄存器、程序計(jì)數(shù)器、用戶棧、狀態(tài)寄存器、內(nèi)核棧和各種內(nèi)核數(shù)據(jù)結(jié)構(gòu)(地址空間的頁(yè)表、有關(guān)當(dāng)前進(jìn)程信息的進(jìn)程表、進(jìn)程已打開(kāi)文件的信息的文件表
  • 內(nèi)核調(diào)度器(scheduler)負(fù)責(zé)調(diào)度進(jìn)程,搶占當(dāng)前進(jìn)程,重新開(kāi)始先前被搶占的進(jìn)程。

0x01 101 Inside Process

Process Control

如何控制進(jìn)程?

?

PID

pid > 0

#include <sys/types.h> // for pid_t
#include <unistd.h>
?
pid_t getpid(void); // 獲取進(jìn)程ID
pid_t getppid(void); // 獲取父進(jìn)程ID

Creating and Terminating Process

從程序角度來(lái)看,進(jìn)程總處于以下三種狀態(tài):

  • Running——要么處于CPU執(zhí)行中,要么處于等待被執(zhí)行且最終會(huì)被內(nèi)核調(diào)度。

 

  • Stopped——進(jìn)程被掛起(suspend),且不會(huì)被調(diào)度。當(dāng)收到SIGSTOP、SIGTSTP、SIGTTIN或者SIGTTOU信號(hào)時(shí),進(jìn)程停止,直到收到SIGCONT信號(hào),進(jìn)程再次開(kāi)始運(yùn)行。

 

  • Terminated——進(jìn)程永遠(yuǎn)停止了。三種原因?qū)е陆K止:
  1. 收到一個(gè)默認(rèn)行為時(shí)終止進(jìn)程的信號(hào);
  2. 從主程序返回;
  3. 調(diào)用exit。
#include <sys/types.h>
#include <unistd.h>
/* 創(chuàng)建子進(jìn)程
* 返回:
子進(jìn)程=0,父進(jìn)程=子進(jìn)程PID,出錯(cuò)=-1
*/
pid_t fork(void);
?
#include <stdlib.h>
void exit(int status);

父進(jìn)程通過(guò)調(diào)用fork創(chuàng)建一個(gè)新的運(yùn)行子進(jìn)程,最大的區(qū)別在于不同的PID。

  • fork():一次調(diào)用,返回兩次。
  1. 在調(diào)用進(jìn)程中(父進(jìn)程),返回子進(jìn)程PID;
  2. 在新創(chuàng)建的子進(jìn)程中,在子進(jìn)程中返回0。
  • 并發(fā)執(zhí)行:父子進(jìn)程是并發(fā)運(yùn)行的獨(dú)立進(jìn)程。
  • 相同但是獨(dú)立的地址空間。子進(jìn)程與父進(jìn)程用戶級(jí)虛擬地址空間相同的拷貝,相同的本地變量值、堆、全局變量、以及代碼。如代碼中print出來(lái)不一樣的x。
  • 共享文件:任何打開(kāi)文件描述符相同的拷貝,如stdout。
int main() {
 pid_t pid;
 int x = 1;
?
 pid = fork(); // 在此處分裂出了兩條時(shí)間線!
 if (pid == 0) {// 子進(jìn)程
 printf("child: x=%dn", ++x);
 exit(0);
 }
 // 父進(jìn)程
 printf("parent: x=%dn", --x);
 exit(0);
?
 return 0;
}

out:

parent: x=0

child: x=2

child |————x=2————
father ——————————x=0————
 fork exit

Reap Child Process

進(jìn)程終止時(shí),保持位已終止?fàn)顟B(tài),直到被父進(jìn)程回收(reap)。當(dāng)父進(jìn)程回收已終止的子進(jìn)程,內(nèi)核將子進(jìn)程的退出狀態(tài)傳遞給父進(jìn)程,然后拋棄已終止的進(jìn)程,此刻進(jìn)程不復(fù)存在。

僵尸進(jìn)程(zombie):一個(gè)終止了但還未被回收的進(jìn)程。但是如果父進(jìn)程沒(méi)有回收就終止了,則內(nèi)核安排init進(jìn)程(PID=1)回收僵尸進(jìn)程。

#include <sys/types.h>
#include <sys/wait.h>
?
/* 進(jìn)程可以調(diào)用waitpid等待子進(jìn)程終止或者結(jié)束。
* 默認(rèn)options=0,掛起調(diào)用進(jìn)程,直到它等待集合中的一個(gè)子進(jìn)程終止。如果等待集合中的一個(gè)進(jìn)程在剛調(diào)用的時(shí)刻就已經(jīng)終止了,那么waitpid立即返回。返回已終止的子進(jìn)程PID,并去除該子進(jìn)程。
?
*輸入?yún)?shù)pid:
pid>0,等待集合就是一個(gè)單獨(dú)的子進(jìn)程,進(jìn)程ID等于pid。
pid=-1,等待集合是由父進(jìn)程所有的子進(jìn)程組成。
?
*輸入?yún)?shù)options:
WNOHANGE:等待集合中任何子進(jìn)程都還沒(méi)有終止,立即返回0;默認(rèn)行為還是掛起調(diào)用進(jìn)程直到子進(jìn)程終止。
WUNTRACED:掛起調(diào)用進(jìn)程執(zhí)行,直到集合中有一個(gè)進(jìn)程終止或停止。返回該進(jìn)程PID。
WNOHANGE|WUNTRACED:立刻返回,0=如果沒(méi)有終止或停止的子進(jìn)程;PID=終止或停止的子進(jìn)程PID。
?
*輸入?yún)?shù)status:
WIFEXITED:True=子進(jìn)程是通過(guò)return或者exit終止的;
WEXITSTATUS:返回exit狀態(tài),只有WIFEXITED=True時(shí)被定義;
WIFSIGNALED:True=子進(jìn)程是因?yàn)橐粋€(gè)未被捕獲的信號(hào)終止的;
WTERMSIG:返回導(dǎo)致子進(jìn)程終止信號(hào)量,只有WIFSIGNALED=True被定義;
WIFSTOPPED:True=返回的子進(jìn)程是停止的;
WSTOPSIG:返回引起子進(jìn)程停止的信號(hào)的數(shù)量,只有WIFSTOPPED=True被定義;
?
返回:
成功=子進(jìn)程PID;if WNOHANG=0;
其他錯(cuò)誤=-1(errno=ECHILD,沒(méi)有子進(jìn)程;errno=EINTR,被一個(gè)信號(hào)中斷)
*/
pid_t waitpid(pid_t pid, int *status, int options);
pid_t wait(int *status); //等價(jià)于waitpid(-1, &status, 0);

Sleep

#include <unistd.h>
?
// 返回:seconds left to sleep
unsigned int sleep(unsigned int secs);
?
// 讓調(diào)用函數(shù)休眠,直到收到一個(gè)信號(hào)
// 返回:-1
int pause(void);

Loading and Running Programs

execve函數(shù)在當(dāng)前進(jìn)程的上下文中加載并運(yùn)行一個(gè)新的程序,覆蓋當(dāng)前進(jìn)程的地址空間,但并沒(méi)有創(chuàng)建一個(gè)新進(jìn)程,進(jìn)程PID沒(méi)有改變。

#include <unistd.h>
// 返回:成功=不返回;出錯(cuò)=-1
int execve(const char *filename, const char *argv[],
 const char *envp[]);
// 程序主入口:
int main(int argc, char **argv, char **envp);
int main(int argc, char *argv[], char *envp[]);

Signal

深入理解計(jì)算機(jī)系統(tǒng):進(jìn)程

[ linux Signal(`man 7 signal`) ]

信號(hào)傳遞到目的進(jìn)程包括兩個(gè)步驟:1)發(fā)送;2)接收。

  • 一個(gè)發(fā)出卻沒(méi)被接收的信號(hào)叫做待處理信號(hào)(Pending Signal)。
  • 一個(gè)進(jìn)程有一個(gè)類(lèi)型為k的待處理信號(hào),后面發(fā)送到這個(gè)進(jìn)程的k信號(hào)都會(huì)被丟棄。
  • 也可以選擇性阻塞接收某個(gè)信號(hào),信號(hào)被阻塞時(shí)仍可以發(fā)送,但產(chǎn)生的待處理信號(hào)不會(huì)被接收,直到進(jìn)程取消對(duì)這種信號(hào)的阻塞。
  • 一個(gè)待處理信號(hào)最多只能被接收一次,內(nèi)核為每個(gè)進(jìn)程在pending位向量中維護(hù)待處理信號(hào)集合,而在blocked位向量中維護(hù)被阻塞的信號(hào)集合。
  • 只有接收了k信號(hào),內(nèi)核才會(huì)清除pending中的k位。

Sending Signal

  • 每個(gè)進(jìn)程都只屬于一個(gè)進(jìn)程組,進(jìn)程組ID標(biāo)識(shí)。unix所有發(fā)送信號(hào)的機(jī)制都是基于進(jìn)程組(process group)/
#include <unistd.h>
?
// 返回:調(diào)用進(jìn)程的進(jìn)程組ID
pid_t getpgrp(void);
// 返回:成功=1,錯(cuò)誤=-1
int setpgid(pid_t pid, pid_t pgid);
  • 用/bin/kill程序發(fā)送信號(hào)
  • 發(fā)送信號(hào)9到進(jìn)程15213
  • /bin/kill -9 15213
  • 發(fā)送信號(hào)9到進(jìn)程組15213中的每個(gè)進(jìn)程。
  • /bin/kill -9 -15213
  • 從鍵盤(pán)發(fā)送信號(hào)
  • unix使用作業(yè)(job)表示對(duì)每一個(gè)命令行執(zhí)行而創(chuàng)建的進(jìn)程,至多一個(gè)前臺(tái)作業(yè)和0個(gè)或多個(gè)后臺(tái)作業(yè)。通過(guò)|unix管道連接起多個(gè)進(jìn)程。
  • shell位每個(gè)作業(yè)創(chuàng)建一個(gè)獨(dú)立的進(jìn)程組。進(jìn)程組ID是取自job中父進(jìn)程中的一個(gè)。
  • Ctrl + C發(fā)送SIGINT信號(hào)到前臺(tái)進(jìn)程組中的每一個(gè)進(jìn)程,終止前臺(tái)作業(yè)。
深入理解計(jì)算機(jī)系統(tǒng):進(jìn)程

[ 前臺(tái)進(jìn)程子進(jìn)程和父進(jìn)程具有相同的進(jìn)程組ID。]

  • 用KILL函數(shù)發(fā)送信號(hào)。
#include <signal.h>
// 輸入?yún)?shù)pid:
// pid>0:發(fā)送SIGKILL給進(jìn)程pid
// pid<0:發(fā)送SIGKILL給進(jìn)程組abs(pid)
// 返回:成功=0,失敗=-1
int kill(pid_t pid, int sig);
  • alarm函數(shù)發(fā)送信號(hào)
#include <unistd.h>
// 發(fā)送SIGALRM給調(diào)用進(jìn)程,如果secs位0,則不會(huì)調(diào)度alarm。任何情況,對(duì)alarm調(diào)用都將取消任何pending alarm,并返回pending alarm在被發(fā)送前還剩下的秒數(shù)。
// 返回:前一次alarm剩余的秒數(shù),0=以前沒(méi)有設(shè)定alarm
unsigned int alarm(unsigned int secs);
?
?
/* 定時(shí)1s觸發(fā)alarm handler,5s結(jié)束 */
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
?
?
void handler(int sig) {
 static int beeps = 0;
 printf("BEEPn");
 if (++beeps < 5) {
 alarm(1);
 } else {
 printf("BOOM!n");
 exit(0);
 }
}
?
?
int main() {
 signal(SIGALRM, handler);
 alarm(1);
 for(;;);
 exit(0);
}

Receiving Signals

wtf:
當(dāng)異常處理程序返回時(shí),準(zhǔn)備轉(zhuǎn)移控制權(quán)給進(jìn)程p時(shí),會(huì)檢查非被阻塞的待處理信號(hào)的集合(pending&~blocked)
if 集合為空:
 進(jìn)程p的邏輯控制流下一跳指令
else:
 選擇某個(gè)最小信號(hào)k,強(qiáng)制p接收信號(hào)k
 goto wtf

每個(gè)信號(hào)類(lèi)型預(yù)定義的默認(rèn)行為(查看Figure8.25):

  • 進(jìn)程終止
  • 進(jìn)程終止并轉(zhuǎn)存儲(chǔ)器(dump core)
  • 進(jìn)程停止直到被SIGCONT信號(hào)重啟
  • 進(jìn)程忽略該信號(hào)
#include <signal.h>
?
?
// 定義信號(hào)處理函數(shù)(signal handler)
// 輸入int為信號(hào)量
typedef void (*sighandler_t)(int);
// 輸入函數(shù)sighandler_t:
// handler=SIG_IGN,忽略類(lèi)型為signum的信號(hào);
// handler=SIG_DFL,重置類(lèi)型為signum信號(hào)的行為。
//
// 返回:成功=指向前次處理程序指針,出錯(cuò)=SIG_ERR(不設(shè)置errno)
sighandler_t signal(int signum, sighandler_t handler); // installing the handler
?
?
?
?
/* ctrl-c中斷sleep,并打印睡眠時(shí)間 */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
?
?
void handler(int sig) {} // 改變SIGINT處理函數(shù)
?
?
int snooze(unsigned int sec) {
 int left_sleep_sec = sleep(sec);
 printf("Slept for %d of %d secs.tUser hits ctrl-c after %d secondsn",
 left_sleep_sec, sec, sec-left_sleep_sec);
}
?
?
int main(int argc, char *argv[]) {
 if (SIG_ERR == signal(SIGINT, handler)) {
 exit(-1);
 }
?
?
 unsigned int sleep_sec = 0;
 if (argc > 1) {
 sleep_sec = atoi(argv[1]);
 } else {
 exit(0);
 }
 printf("sleep for %d secondsn", sleep_sec);
 snooze(sleep_sec);
 exit(0);
}

Signal Handling Issues

當(dāng)程序需要捕獲多個(gè)信號(hào)時(shí),問(wèn)題產(chǎn)生了。

  • 待處理信號(hào)被阻塞。Unix信號(hào)處理程序通常會(huì)阻塞當(dāng)前處理程序正在處理的類(lèi)型的待處理信號(hào)k。如果另一個(gè)信號(hào)k傳遞到該進(jìn)程,則信號(hào)k將變成待處理,但是不會(huì)被接收,直到處理程序返回。再次檢查發(fā)現(xiàn)仍有待處理信號(hào)k,則再次調(diào)用信號(hào)處理函數(shù)。
  • 待處理信號(hào)不會(huì)排隊(duì)等待。任意類(lèi)型最多只有一個(gè)待處理信號(hào)。當(dāng)目的進(jìn)程正在執(zhí)行信號(hào)k的處理程序時(shí)是阻塞的,當(dāng)發(fā)送兩個(gè)信號(hào)k,僅第一個(gè)信號(hào)k會(huì)變成待處理,第二個(gè)則直接被丟棄,不會(huì)排隊(duì)等待。
  • 系統(tǒng)調(diào)用可以被中斷。像read、wait和accept調(diào)用過(guò)程會(huì)阻塞進(jìn)程的稱(chēng)謂慢速系統(tǒng)調(diào)用,當(dāng)捕獲到一個(gè)信號(hào)時(shí),被中斷的慢速系統(tǒng)調(diào)用在信號(hào)處理返回時(shí)不再繼續(xù),而是立即返回用戶一個(gè)錯(cuò)誤條件,并將errno設(shè)置為EINTR。(即使sleep被信號(hào)處理捕獲后仍會(huì)返回)

Explicitly Blocking and Unblocking Signals

#include <signal.h>
?
?
// how = SIG_BLOCK, blocked=blocked | set
// how = SIG_UNBLOCK, blocked=blocked &~ set
// how = SIG_SETMASK, blocked = set
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); int sigemptyset(sigset_t *set);
// 將每個(gè)信號(hào)添加到set
int sigfillset(sigset_t *set);
// 添加signum到set
int sigaddset(sigset_t *set, int signum);
// 從set中刪除signum
int sigdelset(sigset_t *set, int signum);
//Returns: 0 if OK, −1 on error
?
?
int sigismember(const sigset_t *set, int signum);
//Returns: 1 if member, 0 if not, −1 on error

Nonlocal Jump

作用允許從一個(gè)深層嵌套的函數(shù)調(diào)用中立即返回。

另一個(gè)作用是使一個(gè)信號(hào)處理程序分支到一個(gè)特殊的位置sigsetjmp/siglongjmp。

#include <setjmp.h>
?
?
int setjmp(jmp_buf env);
int sigsetjmp(sigjmp_buf env, int savesigs);
// Returns: 0 from setjmp, nonzero from longjmps
?
?
void longjmp(jmp_buf env, int retval);
void siglongjmp(sigjmp_buf env, int retval);
// Never returns
?
?
jmp_buf env;
rc=setjmp(env); // 保存當(dāng)前調(diào)用環(huán)境
if(rc == 0) dosomething();
else if (rc == 1) dosomething1(); // 如果
else if (rc == 2) dosomething2();
?
?
int dosomething() {
 longjmp(buf,1); // 跳轉(zhuǎn)到setjmp,返回1
 // longjmp(buf,2); // 跳轉(zhuǎn)到setjmp,返回2
}

操作進(jìn)程工具

STRACE:打印一個(gè)正在運(yùn)行的程序和它的子程序調(diào)用的每個(gè)系統(tǒng)調(diào)用的軌跡。

PS:列出當(dāng)前系統(tǒng)中的進(jìn)程(包括僵尸進(jìn)程)。

TOP:打印關(guān)于當(dāng)前進(jìn)程資源使用的信息。

PMAP:顯示進(jìn)程的存儲(chǔ)器映射。

/proc:一個(gè)虛擬文件系統(tǒng),以ASCII輸出大量?jī)?nèi)核數(shù)據(jù)結(jié)構(gòu)的內(nèi)容。如cat /proc/loadavg,觀察Linux系統(tǒng)上的當(dāng)前的平均負(fù)載。

分享到:
標(biāo)簽:進(jìn)程
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定