1、基礎知識linux
1:進程。服務器
1,進程ID: 非負整數,具備惟一性。網絡
1)ID=0的進程:調度進程/交換進程。內核的一部分。不執行任何磁盤上的程序。ide
2)ID=1的進程:init進程。函數
1-自舉結束時,由內核調用,且不會終止。佈局
2-用於讀取與系統有關的初始化文件。並引導系統至一個狀態。ui
3-使用root權限運行,是全部孤兒進程的父進程。spa
3)ID=2的進程:頁守護進程。負責支持虛擬存儲器系統的分頁操做。命令行
2,僵死進程:已經終止,但其父進程還沒有對其進行善後處理的進程。線程
3,進程調度。
1)UNIX系統只提供基於調度優先級的粗粒度的控制。
2)調度策略和調度優先級由內核肯定。
3)進程能夠經過調整nice值來下降優先級運行。(不可提高)
4)只有特權進程容許提升優先級。(應該指root)
4,父進程和子進程。
1)父進程和子進程只共享正文段。其餘僅爲副本,僅在複製的此刻保持一致。linux中,增長函數clone。能夠控制哪些部分共享,哪些部分不共享。
2)每一個進程都有一個父進程。子進程終止時,父進程獲得通知並獲取子進程的退出狀態。
3)一般進程的父進程是什麼?用戶進程?
4)子進程的用途。
1-父進程但願複製本身。例如:服務器中,等待客戶端服務請求。請求到達,複製一份子進程執行請求。父進程繼續等待請求。
2-進程須要執行另一個程序。此狀況下,fork後將當即調用exec函數。
5,進程組:多個進程的集合。
1)每一個進程組由一個組長進程。組長進程的ID就是進程組ID。
2)進程組中的最後一個進程能夠終止,也能夠轉移到另外一個進程組。
3)進程能夠設置本身和子進程的進程組ID。但子進程調用exec後,就不能再經過父進程修改進程組ID了。
6,會話:包含一個或多個進程組。
1)會話ID爲會話首進程ID。會話首進程稱爲 控制進程。
2)一個會話能夠有一個控制終端。(終端或僞終端設備)
3)會話分爲:一個前臺進程組和多個後臺進程組。
2:進程中的用戶和用戶組。
1,進程中分爲:實際用戶/組,有效用戶/組,設置用戶/組。
1)實際:進程執行用戶。
2)有效:決定進程訪問權限。一般 實際== 有效
3)設置:設置ID由exec函數保存。當有效時,則將設置ID變爲有效ID。
4)stat->st_mode中有兩個特殊標誌位(分別控制用戶和組)。置位做用爲:當執行此文件,進行的有效ID將便爲該文件的全部者ID。(用戶和組由不一樣位控制)
2,設置ID能夠間接得到其餘用戶權限。須要慎重使用。(例:用戶更改本身的密碼,口令文件爲root全部。)
3,非root權限的進程,寫文件時,設置用戶/組ID位會清除。
4,新文件用戶ID爲:進程有效用戶ID。
5:新文件的組ID有兩種狀況(linux 3.2.0):
1)所在目錄的設置組ID置位時:和所在目錄的組ID同樣。
2)所在目錄的設置組ID未置位時:進程有效組ID。
3:進程啓動和終止。
1,啓動:
1)內核使程序執行的惟一方法時調用一個exec函數。
2,正常終止:
1)從main返回。
2)從exit, _exit, _Exit函數調用。
3)最後一個線程: 從啓動例程返回 或 調用pthread_exit.
3,異常終止。
1)調用abort函數。
2)接收到一個信號(終止相關)
3)最後一個線程對取消請求作出響應。
3:C程序的儲存空間佈局。下列順序由高地址到低地址排序。
1,命令行參數和環境變量。
2,棧(stack):往低地址方向增加。保存:自動(臨時)變量 和 函數調用相關信息(形參,返回地址等)
3,堆(head):往高地址方向增加用於動態儲存分配。(例如:new,malloc等)
4,未初始化數據:稱之爲bss段。保存了已經未初始化的全局/靜態變量。
5,初始化數據:保存了已經初始化的全局/靜態變量。
6,包含常量數據:若是不細分,也能夠看成初始化數據的一部分。
7,正文:CPU執行的機器指令保存部分。
低地址 | 正文(text) | 常量數據(rodata) | 初始化數據(data) | 未初始化數據(bss) | heap(堆) --> | unused | <-- stack(棧) | environment | 高地址 |
8,子進程建立時,擁有父進程其餘一切數據的副本,但只有exec程序執行後,才擁有棧和堆。
4:守護進程。
1,基本概念。
1)生存週期長的進程。
2)一般在後臺運行。
3)使用 ps -axj能夠顯示進程。守護進程的名字出如今方括號[ ] 中。
4)須要在進程上下文執行工做,單不被用戶層進程上下文調用的內核組件,一般都有本身的守護進程。
5)守護進程一般以root權限運行。
2,產生日誌消息的方式。
1)內核例程調用log函數。
2)守護進程調用syslog函數產生。
3)將日誌消息發送向UDP端口514。(網絡用戶也可使用)
4,守護進程遵循下列通用慣例。
1)若是守護進程使用鎖文件。通常儲存在/var/run目錄下。鎖文件名爲name.pid
2)如支持配置選項,目錄爲 /etc 名字爲 name.conf
3)可使用命令行啓動,一般由系統初始化腳本啓動
4)若是守護進程由配置文件,那啓動時會讀取該文件。以後通常不會再查看。若是修改配置,須要重啓守護進程。
2、相關函數。
1 退出函數。 void exit( int status ) void _Exit( int status ) void _eixt( int status ) // 1 stdlib.h 包含exit _Exit.unistd.h包含_exit // 2 參數status 將做爲main函數的返回值返回。 // 3 只有exit函數而沒有return返回時,部分編譯器可能會出現報錯或者警告 2 登記一個函數爲終止處理函數。 // 1 終止處理函數將由exit函數自動調用。 // 2 註冊順序和調用順序相反。 // 3 能夠用sysconf函數來查詢最大終止程序數(最少支持32個) int atexit( void (*func)(void) ); 3 內存分配函數。 void *malloc( size_t size ); // 按大小分配內存。 void *calloc( size_t nobj, size_t size ); // 按指定數量和指定長度的對象分配儲存空間。 void *realloc( void *ptr, size_t newsize ); //增長/減小之前分配區的長度。 void free( void *ptr ); //釋放內存。 // 1 分配函數返回的指針必定要適當對齊。例:double必須在8的倍數地址單元處開始。 // 2 由隱性的轉換規則。如無,則默認返回爲int。沒有正確的轉換類型可能致使隱性的系統錯誤。 4 環境變量函數 int putenv( char *str ); // 參數形式:name=value。不然出錯。 int setenv( const char *name, const char *value, int rewrite ); // 參數rewrite 非零時,會強制寫。不然,不會進行覆蓋操做。 int unsetenv( const char *name ); // 刪除一個環境變量。 5 進程資源的設置和查詢 int getrlimit( int resource, struct rlimit *rlptr ); // 查詢 int setrlimit( int resource, const struct rlimit *rlptr ); // 設置(更改) // 1 軟限制 <= 硬限制。 // 2 任何進程均可以下降硬限制。此過程不可逆。 // 3 root用戶才能夠增長硬限制。 // 4 資源限制會影響到子進程。 6 查詢 子進程終止狀態 函數。 pid_t wait( int *statloc ); pid_t waitpid( pid_t pid, int *statloc, int options ); // 1 參數pid:==-1 等待任一子進程,>0 等待與pid相同ID的子進程,==0 等待組ID等於調用進程組ID的任一子進程,<-1 等待組ID等於pid絕對值的任一子進程。 int waitid( idtype_t idtype, id_t id, siginfo_t *infop, int options ); pid_t wait3( int *statloc, int options, struct rusage *rusage ); pid_t wait4( pid_t pid, int *statloc, int options, struct rusage *rusage ); // 1 三種狀況:無終止子進程,則阻塞。有子進程終止,而且有信號發出,則返回該子進程的終止狀態。進程自己沒有任何子進程,則返回出錯。 // 2 waitpid函數能夠選擇無終止子進程時,不阻塞 7 建立子進程 pid_t fork(void); pid_t vfork(void); // 1 調用一次,返回兩次。父進程返回子進程ID,子進程返回0。返回順序,取決於執行順序。 // 2 可能的失敗緣由:超過可擁有的最大ID數 或 系統中進程數量過多(系統自己已經存在問題) // 3 vfork函數:保證子進程先運行。且必須先exec執行子進程。如不執行,則會在父進程棧中進行運行。 // 4 嘗試代碼後,懷疑,從fork開始,就會有2個進程同時執行 fork 以後的代碼。 8 啓動函數。 int execl( const char * pathname, const char *arg0, ...) int execv( const char * pathname, char *const argv[] ) int execle( const char * pathname, const char *arg0, ...) int execve( const char * pathname, char *const argv[], char *const envp[] ) int execlp( const char * pathname, const char *arg0, ...) int execvp( const char * pathname, char *const argv[] ) int fexecve( int fd, char *const argv[], char *const envp[] ) // 1 filename包含/ 則看成路徑名。都則按照PATH環境變量,在各目錄搜索可執行文件。 // 2 PATH變量中包含目錄表,用 : 隔開。例:PATH=/bin : /usr/bin 8 操做 進程 用戶/組 ID int setuid( uid_t uid ); // 設置有效用戶ID。若是有root權限,還能夠更改實際用戶。 int setgid( gid_t gid ); // 設置有效組ID。若是有root權限,還能夠更改實際組。 int setreuid( uid_t ruid, uid_t euid ); // 交換實際用戶和有效用戶ID。 int setregid( gid_t rgid, gid_t egid ); // 交換實際組和有效組ID。 int seteuid( uid_t uid ); // 僅設置有效用戶ID。 int setegid( uid_t gid ); // 僅設置有效組ID。 // 1 只有root用戶才能夠更改實際用戶ID。 // 2 普通用戶不能進行權限之外的其餘操做。 9 進程調度函數(優先級) int nice( int incr ); // 更改優先級,只能更改進程自己的優先級(擁有root權限除外)。 int getpriority( int which, id_t who ); // 得到nice值 int setpriority( int which, id_t who, int value ); // 設置nice值。 // 1 nice值輸入過大或太小,函數都會自動進行調整。 10 進程時間 結構體 clock_t times( struct tms *buf ); struct tms { clock_t tms_utime; //用戶CPU時間。 clock_t tms_stime; //系統CPU時間。 clock_t tms_cutime; //用戶CPU時間,以及終止子進程時間 clock_t tms_cstime; //系統CPU時間,以及終止子進程時間 } 11 進程組 int setpgid( pid_t pid, pid_t pgid ); // 加入/建立一個進程組 // 1 調用該函數後,進程和控制終端的聯繫會被切斷。 pid_t tcgetpgrp( int fd); // 獲得進程進程組ID int tcsetpgrp( int fd, pid_t pgrpid ); // 設置前臺進程組ID。 12 會話 pid_t setsid( void ); // 創建一個新會話。 pid_t tcgetsid( int fd ); // 會話首進程的進程組ID。 13 守護進程函數。 void openlog( const char *ident, int option, int facility ); void syslog( int priority, const char *format ); void closelog( void ); int setlogmask( int maskpri );
3、