程式程式設計2 – Unix環境高階程式設計8章讀書筆記
Process Control
1 Process Identifiers
1. PID=0一般是排程程式,又稱為swapper
2. PID=1一般是init程式,在引導過程之後啟動,負責啟動整個UNIX系統,所有Orphaned子程式都會自動成為init的子程式
3. PID=2一般是頁面守護程式,負責將虛擬記憶體的換頁
4. 下面函式被用來獲得pid:
#include <unistd.h> pid_t getpid(void); 返回程式pid pid_t getppid(void); 返回父程式的pid uid_t getuid(void); 返回程式的user id
uid_t geteuid(void); 返回程式的effective user id gid_t getgid(void); 返回程式的group id gid_t getegid(void); 返回程式的effective group id |
2 fork
fork函式原型如下:
#include <unistd.h> pid_t fork(void); 在子程式中返回0,父程式中返回實際的子程式pid,-1則出錯 |
1. 這個函式建立出一個和父程式相同的子程式,比較特別的是子程式也會從這個函式呼叫,和父程式只是返回值不同。
2. 子程式起初和父程式共享同樣的實體記憶體,當某個頁面被修改的時候,系統會給子程式分配新的空間給這個頁面。這個行為被稱為COW (Copy On Write)
3. 父程式還是子程式先繼續執行無法預測
4. 父程式的所有檔案描述符在子程式中都被呼叫dup函式複製,並且檔案offset是在子程式和父程式之中共享的
5. 子程式繼承了父程式的下列特性:
a. File Descriptors
b. Real user ID, real group ID, effective user ID, effective group ID
c. Supplementary group IDs
d. Process group ID
e. Session ID
f. Controlling terminal
g. Set-user-ID & set-group-ID flags
h. Working directory
i. Root directory
j. File mode creation mask
k. Signal mask & dispositions
l. The close-on-exec flag for any open file descriptions
m. Environment
n. Attached shared memory segments
o. Memory mapping
p. Resource limits
6. 子程式和父程式不同的地方有:
a. fork函式的返回值
b. Process ID
c. Parent process ID
d. tms_utime, tms_stime, tms_cutime, tms_cstime = 0
e. File lock不被子程式繼承
f. Pending alarm被清除
g. Pending signal被清除
7. fork失敗的可能性有:
a. 系統中的程式過多
b. 超過系統設定的limit
3 vfork
vfork的原型和返回值和fork相同,區別在於:
1. 建立的子程式和父程式共享同一個地址空間
2. 建立的子程式一般的作用是再呼叫exec建立一個新的程式,在某些系統上可能會有一些優化
4 exit
1. 當父程式先於子程式退出的時候,子程式會變成orphaned並被init程式“收養”,init成為這些子程式的新的父程式。
2. 當子程式先於父程式退出的時候,而且父程式也沒有用wait, waitpid函式等待子程式結束,則子程式的部分資訊會被儲存起來,如PID,退出狀態,CPU時間等,直到子程式被wait。處於這樣狀態的子程式被稱為zombie
3. 被init程式inherit的子程式如果中止不會變成zombie,因為init會自動當程式結束的時候呼叫wait
5 wait & waitpid
1. 當子程式結束的時候,父程式會收到SIGCHLD通知
2. 程式可以呼叫wait / waitpid等待此Signal:
a. 當所有子程式都在執行的時候,會block
b. 當某個子程式中止,成為zombie的時候,立刻返回
c. 如果沒有任何子程式,則返回錯誤
3. wait和waitpid函式原型如下:
#include <unistd.h> pid_t wait(void); pid_t waitpid(pid_t pid, int *statloc, int options); 正常情況下返回pid,或者0(waitpid在非block模式下才有可能返回),-1代表錯誤 |
4. 這兩個函式區別如下:
a. Wait函式會因為等待子程式結束而block,而waitpid有一個option可以允許waitpid函式不block
b. waitpid等待某個特定程式
5. waitpid函式的statloc引數儲存了退出程式的狀態,當然也可以傳NULL。這個狀態通常和實現相關,不過可以用wait.h中定義的macro來檢測。
a. WIFEXITED(status):返回值
b. WIFSIGNALED(status):返回造成退出的signal的number
c. WIFSTOPPED(status):是否被stop,可以用WSTOPSIG(status)來獲得具體的signal
d. WIFCONTINUED(status):返回是否被continue
6. waitpid的pid引數:
a. pid == -1:等待任意子程式,等價於wait
b. pid > 0,等待pid指定的子程式
c. pid == 0,等待和呼叫程式相同group id的任意子程式
d. pid < -1,等待任意group id = pid的絕對值的子程式
7. waitpid的options引數可以是下面的組合:
a. WCONTINUED:等待任何指定的子程式在stop之後被continue
b. WNOHANG:如果還沒有退出,不block,返回0
c. WUNTRACED:被stopped的程式
6 waitid
waitid函式在waitpid函式上提供了額外的靈活性:
#include <unistd.h> int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options); 成功返回0,錯誤返回-1 |
1. idtype_t可以是下面的值之一:
a. P_PID:等待某指定的子程式
b. P_PGID:等待任意指定group id的子程式
c. P_ALL:任意子程式,id會被忽略
2. Options可以是下面的值:
a. WCONTINUED:等待被stop並且被continue的程式
b. WEXITED:等待退出的程式
c. WNOHANG:如果沒有子程式需要等待則立刻返回
d. WNOWAIT:不會將zombie子程式的退出狀態撤銷,下次呼叫wait系列函式的時候還可以繼續獲得這個退出狀態
e. WSTOPPED:等待被stop的程式
3. Infop指向一個siginfo_t結構,表示使得程式退出的signal的產生原因:
struct siginfo_t { int si_signo; /* signal */ int si_errno; /* errrno */ int si_code; /* 額外資訊,和具體signal相關 */ pid_t si_pid; /* 傳送signal程式的pid */ uid_t si_uid; /* 傳送signal的程式的uid */ void *si_addr; /* 產生fault(SIG_SEGV)的地址 */ int si_status; /* 退出值或者signal數值 */ long si_band; /* SIGPOLL的band數值 */ }; |
7 wait3 & wait4
這兩個函式的用處是返回額外的關於程式資源使用狀況的資訊,以struct rusage *rusage的形式返回
8 exec functions
之前提到了vfork可以建立一個並非是父程式copy的子程式,專門用來呼叫exec函式。exec系列函式的作用是呼叫一個新的程式在該程式中執行,PID不改變,也沒有建立新程式,只是replace當前的程式,該函式成功情況下不會返回。原型如下:
#include <unistd.h> int execl(const char *pathname, const char *arg0, … /* (char *) 0 */ ); int execv(const char *pathname, char *const argv[]); int execle(const char *pathname, const char *arg0, … /* (char *)0, char *const envp[] */); int execve(const char *pathname, char *const argv[], char *const envp[]); int execlp(const char *filename, const char *arg0, … /* (char *)0 */ ); int execvp(const char *filename, char *const argv[]); 錯誤返回-1,成功不會返回 |
1. 前面4個是pathname,後面兩個則是filename。Filename如果有’/’字元,則被認為是pathname,否則認為是filename並會在PATH路徑指定的位置查詢
2. execlp和execvp對於非可ELF執行檔案會認為是Shell指令碼來處理
3. execl, execlp, execle需要每個引數單獨傳遞,NULL作為結束。而execv, execvp, execve則是傳入argv
4. execle, execve可以傳入環境,其他四個函式則會使用environ變數中的內容
總結一下,各個字元代表的意義是:
1. v:用argv傳入引數
2. l:用每個引數作為argument傳入
3. e:傳入環境,沒有的話則使用environ變數的值
4. p:傳入的是filename,並會處理PATH的內容,否則是pathname
需要注意的是,exec呼叫之後程式的real user ID和real group ID不變,如果被執行的程式的set-user-ID位被設定,effective user ID被設定成owner ID。也就是說,如果一個normal user用exec執行了一個owner為superuser的程式,並且該程式的set-user-id被設定,那麼一旦該程式被執行,該程式的effective user id=super user,這可能是潛在的安全問題。
9 Change User IDs and Group IDs
1. User ID & Group ID的意義如下:
ID |
Description |
real user ID real group ID |
真正的user ID和group ID |
effective user ID effective group ID supplementary group ID |
用於檔案訪問許可權檢查 |
saved set-user-ID saved set-group-ID |
由exec儲存起來。如果沒有提供這個feature(通過_POSIX_SAVED_IDS)可以判斷,則這些ID不存在 |
2. setuid 和setgid函式用來設定User ID / Group ID,原型如下:
#include <unistd.h> int setuid(uid_t uid); int setgid(gid_t gid); 成功返回0,錯誤返回-1 |
3. setuid的規則如下:
a. 有超級使用者的許可權的程式,setuid會修改real user id, effective user ID, & saved set-user-ID為uid
b. 當程式沒有超級使用者許可權,並且uid = real user ID / saved set-user-ID的話,setuid會修改effective user ID為uid
c. 否則,errno被設定為EPERM,返回-1
d. 上面這些規則也適用於setgid
4. 對於uid下面規則成立:
a. 只有超級使用者的程式才可以改變real user ID。一般情況下不會改變real user ID
b. 當程式的set-user-ID位被設定,exec才會設定effective user ID為程式的user ID,否則則不改變
c. Saved set-user-ID從exec所設定的effective user ID拷貝而來
5. POSIX.1還提供了兩個函式seteuid和setegid,用來修改effective user ID / effective group ID
a. 對於一般使用者,只能設定effective user ID為real user ID或者saved set-user-ID,不能為其他值
b. 對於超級使用者,可以設定effective user ID為任意值
10 system
1. System函式用於執行引數中給出的string,呼叫程式
2. System函式的基本實現是呼叫fork,在子程式中呼叫exec執行/bin/sh或者其他shell,執行命令,父程式呼叫waitpid等待子程式的結束
3. 之前在討論exec的時候提到過, exec呼叫之後程式的real user ID和real group ID不變,如果被執行的程式的set-user-ID位被設定,effective user ID被設定成owner ID。也就是說,如果一個normal user用exec執行了一個owner為superuser的程式,並且該程式的set-user-id被設定,那麼一旦該程式被執行,該程式的effective user id=super user (real user ID不變),這可能是潛在的安全問題。這個問題同樣適用於system
11 User Identification
getlogin函式可以獲得使用者名稱:
#include <unistd.h> char *getlogin(void); 成功返回具體name,錯誤返回NULL |
12 Process Times
times函式可以獲得和程式相關的時間:
#include <sys/times.h> clock_t times(struct tms *buf); 成功返回wall clock time,錯誤返回-1 |
tms結構如下:
struct tms { clock_t tms_utime; /* user CPU time */ clock_t tms_stime; /* system CPU time */ clock_t tms_cutime; /* user CPU time, terminated children */ clock_t tms_cstime; /* system CPU time, terminated children */ }; |
作者: ATField
Blog: http://blog.csdn.net/atfield
相關文章
- 程式程式設計1 – Unix環境高階程式設計7章讀書筆記程式設計筆記
- 程式程式設計3 - UNIX高階環境程式設計第9章讀書筆記程式設計筆記
- UNIX訊號(signal)程式設計 - UNIX高階環境程式設計第10章讀書筆記程式設計筆記
- unix環境高階程式設計(中)-程式篇程式設計
- UNIX系統程式設計的瑞士軍刀 --《UNIX環境高階程式設計》書評程式設計
- 使用pthread庫進行多執行緒程式設計2 - UNIX高階環境程式設計第12章讀書筆記thread執行緒程式設計筆記
- C#高階程式設計 讀書筆記C#程式設計筆記
- 使用pthread庫進行多執行緒程式設計1 - UNIX環境高階程式設計第11章讀書筆記thread執行緒程式設計筆記
- python高階程式設計讀書筆記(一)Python程式設計筆記
- unix環境高階程式設計(上)-檔案篇程式設計
- unix環境高階程式設計(下)-高階IO和程式間通訊篇程式設計
- Objective-C高階程式設計讀書筆記(二)Object程式設計筆記
- Objective-C高階程式設計讀書筆記(一)Object程式設計筆記
- 《UNIX環境高階程式設計》(APUE) 筆記第十一章 - 執行緒程式設計筆記執行緒
- UNIX環境高階程式設計——執行緒和fork程式設計執行緒
- 《JavaScript 高階程式設計》精讀筆記JavaScript程式設計筆記
- Objective-C高階程式設計讀書筆記之GCDObject程式設計筆記GC
- Objective-C高階程式設計讀書筆記之blocksObject程式設計筆記BloC
- UNIX環境高階程式設計習題——第二章程式設計
- 推薦一本技術類書籍:Unix環境高階程式設計程式設計
- 《unix環境高階程式設計》書中原始碼編譯問題解決程式設計原始碼編譯
- JavaScript高階程式設計筆記JavaScript程式設計筆記
- Unix環境高階程式設計——開源的標準化努力程式設計
- node.js高階程式設計閱讀筆記Node.js程式設計筆記
- Objective-C高階程式設計讀書筆記之記憶體管理Object程式設計筆記記憶體
- Unix環境高階程式設計——第一章-UNIX基礎知識程式設計
- JavaScript 高階程式設計 第三章 讀書筆記(1)JavaScript程式設計筆記
- 第一篇:《UNIX 環境高階程式設計》編譯環境的搭建程式設計編譯
- 《LINUX與UNIX SHELL程式設計指南》讀書筆記(轉)Linux程式設計筆記
- 《UNIX環境高階程式設計》apue原始碼Ubuntu下的編譯程式設計原始碼Ubuntu編譯
- 【筆記】《JavaScript高階程式設計(第3版)》(2)筆記JavaScript程式設計
- 《程式設計匠藝》讀書筆記程式設計筆記
- Java高階程式設計筆記 • 【第4章 網路程式設計】Java程式設計筆記
- Unix高階程式設計學習筆記--系統呼叫簡介程式設計筆記
- 《JavaScript 高階程式設計》 讀書筆記--從原型鏈複習繼承JavaScript程式設計筆記原型繼承
- 《Go 語言程式設計》讀書筆記(十一)底層程式設計Go程式設計筆記
- 一個程式設計師的讀書筆記:程式設計的反思程式設計師筆記
- 《JavaScript高階程式設計》筆記:DOM(十)JavaScript程式設計筆記