一.進程創建相關
1. 程序是靜態的,沒有執行的概念,進程是動態的,是程序的執行過程,包括動態創建,調度和消亡的過程。
2. PCB task_struct #include<linux/sched.h>
PID PPID
Getpid(), getppid()
進程包括 代碼段 數據段 和堆棧段
3.
Fork返回值如果大於0,是父進程的返回值,0 爲子進程的返回值
子進程從父進程中繼承了整個進程的地址空間,包括進程上下文,進程堆棧,內存信息,打開的文件描述符,信號控制設定,進程優先級,進程組號,當前工作目錄,根目錄,資源限制,控制終端等,而子進程所獨有的就是它的進程號,資源使用和計數器。
一般而言現在進程的創建都使用copy-on-write技術
Exec函數族提供了一個進程中啓動另一個程序執行的方法。
一般情況下,都是使用這種方法,是的好像通過應用程序產生了一個新的進程。
Execl list 表示參數逐個列舉的方式
Execv vertor 表示將所有參數整體構造指針數組傳遞
Execle enviroment 可傳遞新進程環境變量
Execlp 可執行文件查找方式爲文件名
例如,
(1) execlp(“ps”,”ps”,”-ef”,NULL)
List + p 以文件名得方式查找,所以第一參數 文件名爲 “ps”
List 參數逐個列舉的方式 “ps” “-ef” NULL
(2) execl(“/bin/ps”,”ps”,”-ef”,NULL)
沒有P,表示是按照路徑來查找執行文件
(3) char *envp[]={“PATH=/tmp”,”USER=sunq”,NULL};
execle(“/bin/env”,”env”,NULL,envp)
envp就是傳遞的環境變量
(4) execve
Char *arg[]={“evn”,NULL} 命令列表
char *envp[]={“PATH=/tmp”,”USER=sunq”,NULL}; 命令參數列表
execve(“/bin/env”,arg,envp)
事實上,最終調用的均爲execve
4. exit和_exit
exit在退出之前檢查文件打開情況,將文件緩存區中的內容寫回文件,即清理I/O緩存。而_exit則直接退出
舉個例子的話,是printf
Printf是IO緩衝方式的函數,在函數遇到“/n”是自動將數據從緩衝區中讀出
例如調用
Printf(“test1/n”);printf(“test2”);
調用exit(0)的話 會顯示 test1 test2
如果調用_exit(0),則之顯示test1
5. wait和waitpid
wait是waitpid的一個特例,
status 爲NULL,表示以任意狀態結束的子進程
非空 則表示 指定狀態結束的子進程
函數的返回值 爲0 表示沒有子進程退出(只在非阻塞模式下有意義)
正常時,返回子進程的進程號
wait是阻塞等待子進程的結束,而waitpid也可以設置非阻塞模式等待進程退出
例如,
Pc=fork();
If(pc>0) //父進程
{ //以任意狀態結束的子進程
Do
{
Pr=Waitpid(pc,NULL,WNOHANG)//非阻塞,
Printf(“wait …/n”);
Sleep(1);
}while(pr==0)
}
如果使用waitpid(pc,NULL,0)//則爲阻塞模式,直到指定的子進程退出爲止、
二.Linux下守護進程創建(用戶空間)
守護進程,daemon進程,是linux下的後臺服務程序,通常獨立於控制終端並且週期性的執行某個任務或者等待某個事件的發生。
一般在控制終端運行的程序都依附於這個終端,當終端關閉,則對應的進程會自動關閉,而守護進程則脫離了這種限制。
守護進程的編寫步驟
1. 創建子進程 父進程退出
這麼操作的原因是因爲 守護進程需要脫離控制終端,父進程退出之後,控制終端認爲該進程已經結束,從而脫離控制終端。而此時該子進程沒有父進程,有init進程作爲其父進程。
2. 在子進程中創建新的對話
使用setsid()
該函數用於創建一個新的會話,並且擔任該會話組的組長。(否則還受原來的會話組和進程組的控制,因爲子進程繼承了父進程的會話組,進程組,控制終端)
這樣,進程就脫離了原來會話組控制,擺脫原來進程組的控制,擺脫原控制終端的控制。
具體的會話組 與進程組的關係如下圖所示
3. 改變當前目錄爲根目錄
由於子進程繼承了父進程的當前工作目錄,爲了保證不會受目錄的影響(比如mount出來的目錄),將根目錄作爲守護進程的目錄
Chdir(“/”)
4. 重設文件權限掩碼
由於子進程繼承了父進程的權限掩碼,擺脫該權限掩碼,自己設定進程的權限掩碼
Umask(0)
5. 關閉文件描述符
因爲守護進程已經脫離了控制終端,所以終端對應的標準輸入0,標準輸出1,標準出錯2的文件描述符沒有存在的意義,將這些描述符關閉,釋放資源。
#define MAXFILE 65535 //
For(i=0;i<MAXFILE;i++)
Close(i);
三.守護進程的出錯調試
因爲守護進程脫離了控制終端,所以只能通過寫文件的方式進行調試
使用openlog,closelog,syslog
對應的log文件在/var/log/message下
Openlog(“XXX”,LOG_PID,LOG_DAEMON);
Syslog(LOG_ERR,”open”);