版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、第五章第五章 進程、信號和消息隊列進程、信號和消息隊列1 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列25.1 什么是進程“一個其中運行著一個或多個線程的地址空間和這些線一個其中運行著一個或多個線程的地址空間和這些線程所需要的系統(tǒng)資源。程所需要的系統(tǒng)資源?!薄罢谶\行的程序。正在運行的程序。”進程由程序代碼、數(shù)據(jù)、變量(占用著系統(tǒng)內(nèi)存)、打進程由程序代碼、數(shù)據(jù)、變量(占用著系統(tǒng)內(nèi)存)、打開的文件(文件描述符)和環(huán)境組成。開的文件(文件描述符)和環(huán)境組成。 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列35.2 進程的結(jié)構(gòu)多進
2、程的管理方式多進程的管理方式示例:兩個用戶同時運行示例:兩個用戶同時運行g(shù)rep程序程序搜索結(jié)束之前運行搜索結(jié)束之前運行ps命令命令 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列45.2 進程的結(jié)構(gòu)多進程的管理方式多進程的管理方式示例:兩個用戶同時運行示例:兩個用戶同時運行g(shù)rep程序程序搜索結(jié)束之前運行搜索結(jié)束之前運行ps命令命令 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列55.2 進程的結(jié)構(gòu)進程表進程表Linux進程表是一個數(shù)據(jù)結(jié)構(gòu),其中保存了當前所有進程的相進程表是一個數(shù)據(jù)結(jié)構(gòu),其中保存了當前所有進程的相關(guān)信息,包
3、括關(guān)信息,包括PID、狀態(tài)、命令字符串等(參見、狀態(tài)、命令字符串等(參見ps命令輸出命令輸出項)。項)。操作系統(tǒng)通過操作系統(tǒng)通過PID對進程進行管理,對進程進行管理,PID是進程表的索引。是進程表的索引。系統(tǒng)可同時運行的進程數(shù)只與可用于建立進程表項的內(nèi)存容量系統(tǒng)可同時運行的進程數(shù)只與可用于建立進程表項的內(nèi)存容量有關(guān)。有關(guān)。父進程與子進程父進程與子進程Linux啟動時運行一個名為啟動時運行一個名為init的進程,該進程是系統(tǒng)運行的第的進程,該進程是系統(tǒng)運行的第一個進程,它的一個進程,它的PID為為1。一般進程一般進程(除除init外外)都是由一個都是由一個“父進程父進程”創(chuàng)建的,被父進程創(chuàng)創(chuàng)建的
4、,被父進程創(chuàng)建的進程稱為建的進程稱為“子進程子進程”,init進程是其他所有進程的祖先進程。進程是其他所有進程的祖先進程。 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列65.2 進程的結(jié)構(gòu)進程狀態(tài)進程狀態(tài)STATSTAT代碼代碼說明說明S S睡眠。通常是在等待某個事件的發(fā)生。睡眠。通常是在等待某個事件的發(fā)生。R R運行運行/ /可運行。即在運行隊列中,處于正在運行或即將運行狀態(tài)。可運行。即在運行隊列中,處于正在運行或即將運行狀態(tài)。D D不可中斷的睡眠(等待)。通常是在等待輸入或輸出完成。不可中斷的睡眠(等待)。通常是在等待輸入或輸出完成。T T停止。通常是被
5、停止。通常是被shellshell作業(yè)控制所停止,或處于調(diào)試器控制下。作業(yè)控制所停止,或處于調(diào)試器控制下。Z Z僵尸(僵尸(zombiezombie)進程。)進程。N N低優(yōu)先級任務(wù)。低優(yōu)先級任務(wù)。s s進程是會話期首進程。進程是會話期首進程。+ +進程屬于前臺進程組。進程屬于前臺進程組。l l進程是多線程的。進程是多線程的。 高優(yōu)先級任務(wù)。高優(yōu)先級任務(wù)。 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列7system函數(shù)函數(shù)可以調(diào)用標準庫函數(shù)可以調(diào)用標準庫函數(shù)system在程序內(nèi)啟動另一個程序,從而創(chuàng)在程序內(nèi)啟動另一個程序,從而創(chuàng)建一個新進程。建一個新進程。#
6、include int system(const char *command);說明說明ucommand待運行的程序(命令字符串)。待運行的程序(命令字符串)。u返回值返回值無法啟動無法啟動shell時,返回時,返回127;其它錯誤時返回其它錯誤時返回-1;否;否則,返回命令的退出碼。則,返回命令的退出碼。usystem函數(shù)運行函數(shù)運行command命令并等待該命令完成,本質(zhì)是調(diào)用:命令并等待該命令完成,本質(zhì)是調(diào)用:/bin/sh c command。u注:注:使用使用system函數(shù)并非啟動其他進程的理想手段,因其必須先函數(shù)并非啟動其他進程的理想手段,因其必須先啟動一個啟動一個shell,再
7、使用該,再使用該shell執(zhí)行相應的命令。執(zhí)行相應的命令。5.3 創(chuàng)建進程 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列85.3 創(chuàng)建進程system函數(shù)函數(shù)示例示例#include #include int main() printf(Running ps with systemn); system(ps -ef); printf(Done.n); exit(0); Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列9替換進程映像替換進程映像可以調(diào)用可以調(diào)用exec系列函數(shù)把當前進程替換為一個新進程。系列函數(shù)把當前進程替換為一
8、個新進程。#include extern char *environ;int execl(const char *path, const char *arg, .);int execlp(const char *file, const char *arg, .);int execle(const char *path, const char *arg, ., char * const envp);int execv(const char *path, char *const argv);int execvp(const char *file, char *const argv);int exe
9、cve(const char *filename, char *const argv, char *const envp);說明說明upath待運行的程序全路徑名(命令字符串)。待運行的程序全路徑名(命令字符串)。ufile待運行的程序名,通過待運行的程序名,通過PATH環(huán)境變量搜索其路徑。環(huán)境變量搜索其路徑。uarg命令參數(shù)。命令參數(shù)。uargv命令參數(shù)。命令參數(shù)。uenvp傳遞給待運行程序的環(huán)境變量。傳遞給待運行程序的環(huán)境變量。u返回值返回值成功時不返回(原程序不再執(zhí)行)成功時不返回(原程序不再執(zhí)行);出錯時返回出錯時返回-1,并設(shè)置,并設(shè)置errno變量。變量。5.3 創(chuàng)建進程 Unix
10、/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列105.3 創(chuàng)建進程替換進程映像替換進程映像用法用法#include /* Example of an argument list */* Note that we need a program name for argv0 */char *const ps_argv =“ps”, “ax”, 0;/* Example environment, not terribly useful */char *const ps_envp =“PATH=/bin:/usr/bin”, “TERM=console”, 0;/* Poss
11、ible calls to exec functions */execl(“/bin/ps”, “ps”, “ax”, 0); /* assumes ps is in /bin */execlp(“ps”, “ps”, “ax”, 0); /* assumes /bin is in PATH */execle(“/bin/ps”, “ps”, “ax”, 0, ps_envp); /* passes own environment */execv(“/bin/ps”, ps_argv);execvp(“ps”, ps_argv);execve(“/bin/ps”, ps_argv, ps_en
12、vp); Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列115.3 創(chuàng)建進程替換進程映像替換進程映像示例示例#include #include #include int main() printf(“Running ps with execlpn”); execlp(“ps”, “ps”, “ax”, 0); printf(“Done.n”); exit(0);說明說明ups命令結(jié)束后,不再返回命令結(jié)束后,不再返回exam09_02程序,所以不會打印出程序,所以不會打印出“Done”。u新進程的新進程的PID、PPID及及nice值和原先的完全一樣。值和原先的
13、完全一樣。uexec系列函數(shù)啟動的新進程的參數(shù)表和環(huán)境變量的總長度是有限制的。上系列函數(shù)啟動的新進程的參數(shù)表和環(huán)境變量的總長度是有限制的。上限由限由ARG_MAX給出,給出, POSIX規(guī)定至少為規(guī)定至少為4KB,Linux中為中為128KB。u原進程中已打開的文件描述符在新進程中仍保持打開(除非原進程中已打開的文件描述符在新進程中仍保持打開(除非“執(zhí)行時關(guān)閉執(zhí)行時關(guān)閉標志標志”被置位)。被置位)。u原進程中打開的目錄流在新進程中被關(guān)閉。原進程中打開的目錄流在新進程中被關(guān)閉。 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列12復制進程映像復制進程映像可以調(diào)用可
14、以調(diào)用fork函數(shù)創(chuàng)建一個新進程。函數(shù)創(chuàng)建一個新進程。#include pid_t fork(void);說明說明u返回值返回值成功時,父進程中返回子進程的成功時,父進程中返回子進程的PID,子進程中返回,子進程中返回0; 失失敗時返回敗時返回-1,并設(shè)置,并設(shè)置errno變量。變量。ufork系統(tǒng)調(diào)用復制當前進程,在進程表中添加一個新的表項,新表項的多系統(tǒng)調(diào)用復制當前進程,在進程表中添加一個新的表項,新表項的多數(shù)屬性與當前進程相同。數(shù)屬性與當前進程相同。u新進程與原進程執(zhí)行的代碼完全相同,但新進程有自己的數(shù)據(jù)空間、環(huán)境新進程與原進程執(zhí)行的代碼完全相同,但新進程有自己的數(shù)據(jù)空間、環(huán)境和文件描述
15、符。和文件描述符。u通常,使用通常,使用fork和和exec系列函數(shù)一起創(chuàng)建多進程環(huán)境。系列函數(shù)一起創(chuàng)建多進程環(huán)境。u典型的典型的fork代碼。代碼。5.3 創(chuàng)建進程典型錯誤為典型錯誤為E_AGAIN子進程超過子進程超過CHILD_MAX限制限制ENOMEM進程表無足夠空間進程表無足夠空間pid_t new_pid;new_pid = fork();switch(new_pid) case -1 : /* Error */ break; case 0 : /* We are child */ break; default : /* We are parent */ break; Unix/Li
16、nux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列13復制進程映像復制進程映像示例示例5.3 創(chuàng)建進程#include #include #include #include int main() pid_t pid; char *message; int n; printf(“fork program startingn”); pid = fork(); switch(pid) case -1: perror(“fork failed”); exit(1); case 0: message = “This is the child”; n = 5; break; default
17、: message = “This is the parent”; n = 3; break; for(; n 0; n-) puts(message); sleep(1); exit(0);運行結(jié)果運行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列14等待進程等待進程在父進程中調(diào)用在父進程中調(diào)用wait函數(shù)可以讓父進程等待任一子進程的結(jié)束。函數(shù)可以讓父進程等待任一子進程的結(jié)束。#include #include pid_t wait(int *status);說明說明ustatus輸出參數(shù),用于獲取子進程的退出狀態(tài)。輸出參數(shù),用于獲取子進程的退出狀態(tài)。
18、u返回值返回值成功時,返回已結(jié)束子進程的成功時,返回已結(jié)束子進程的PID;出錯時返回;出錯時返回-1,并設(shè)置,并設(shè)置errno變量。變量。u以下宏可用于解釋子進程退出狀態(tài)信息。以下宏可用于解釋子進程退出狀態(tài)信息。5.3 創(chuàng)建進程宏宏 說明說明WIFEXITED(status) 如果子進程正常結(jié)束,則取非零值。WEXITSTATUS(status) 如果WIFEXITED非零,則得到子進程的退出碼。WIFSIGNALED(status) 如果子進程因未捕獲的信號而終止,則取非零值。WTERMSIG(status) 如果WIFSIGNALED非零, 則得到引起子進程終止的信號代碼。WIFSTOPP
19、ED(status) 如果子進程已意外終止,則取非零值。WSTOPSIG(status) 如果WIFSTOPPED非零, 則得到引起子進程終止的信號代碼。 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列15等待進程等待進程在父進程中調(diào)用在父進程中調(diào)用waitpid函數(shù)可以讓父進程等待指定的子進程的結(jié)束。函數(shù)可以讓父進程等待指定的子進程的結(jié)束。#include #include pid_t waitpid(pid_t pid, int *status, int options);說明說明upid要等待的子進程的要等待的子進程的PID,值為,值為-1時意為任一子進
20、程。時意為任一子進程。ustatus輸出參數(shù),用于獲取子進程的退出狀態(tài)。輸出參數(shù),用于獲取子進程的退出狀態(tài)。uoptions常見的選項為常見的選項為WNOHANG,意為不掛起調(diào)用者進程。,意為不掛起調(diào)用者進程。u返回值返回值成功時,返回已結(jié)束子進程的成功時,返回已結(jié)束子進程的PID;若指定了;若指定了WNOHANG選選項,但沒有子進程終止,則返回項,但沒有子進程終止,則返回0。出錯時返回。出錯時返回-1,并設(shè)置,并設(shè)置errno變量。變量。5.3 創(chuàng)建進程若要周期性地檢查某個子進程是否已終止,可以使用如下調(diào)用方式:若要周期性地檢查某個子進程是否已終止,可以使用如下調(diào)用方式:waitpid(ch
21、ild_pid, (int *) 0, WNOHANG); Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列16等待進程等待進程示例示例int main() pid_t pid; char *message; int n; int exit_code; printf(“fork program startingn”); pid = fork(); switch(pid) case -1: perror(“fork failed”); exit(1); case 0: message = “This is the child”; n = 5; exit_code
22、= 37; break; default: message = “This is the parent”; n = 3; exit_code = 0; break; 5.3 創(chuàng)建進程 for(; n 0; n-) puts(message); sleep(1); if (pid != 0) int stat_val; pid_t child_pid; child_pid = wait(&stat_val); printf(“Child has finished: PID = %dn”,child_pid); if(WIFEXITED(stat_val) printf(“Child ex
23、ited with code %dn”, WEXITSTATUS(stat_val); else printf(“Child terminated abnormallyn”); exit(exit_code);運行結(jié)果運行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列17僵尸進程僵尸進程子進程終止時,它與父進程之間的關(guān)聯(lián)還會保持(進程表中代表子進子進程終止時,它與父進程之間的關(guān)聯(lián)還會保持(進程表中代表子進程的表項不會立刻釋放,其中含退出碼),直到父進程也正常終止或程的表項不會立刻釋放,其中含退出碼),直到父進程也正常終止或父進程調(diào)用了父進程調(diào)用了wait
24、或或waitpid函數(shù)。函數(shù)。已結(jié)束運行但進程表項仍存在的子進程稱為已結(jié)束運行但進程表項仍存在的子進程稱為“僵尸進程僵尸進程”。如果一個僵尸進程的父進程因異常而終止,該僵尸進程將由如果一個僵尸進程的父進程因異常而終止,該僵尸進程將由init進程接進程接管,它將一直保持在進程表中直到被管,它將一直保持在進程表中直到被init進程發(fā)現(xiàn)并釋放。進程發(fā)現(xiàn)并釋放。應盡量避免產(chǎn)生僵尸進程。應盡量避免產(chǎn)生僵尸進程。5.3 創(chuàng)建進程 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列18概述概述信號是信號是UNIX和和Linux系統(tǒng)為響應某些條件而產(chǎn)生的一個事件。系統(tǒng)為響應某些條
25、件而產(chǎn)生的一個事件。信號一般是因某些錯誤條件而產(chǎn)生的,如內(nèi)存段沖突、浮點處理器錯信號一般是因某些錯誤條件而產(chǎn)生的,如內(nèi)存段沖突、浮點處理器錯誤或非法指令等。誤或非法指令等。信號可作為進程間通信的一種機制,由一個進程發(fā)送給另一個進程。信號可作為進程間通信的一種機制,由一個進程發(fā)送給另一個進程。信號可被生成、捕獲或響應,對于一些信號也可被忽略信號可被生成、捕獲或響應,對于一些信號也可被忽略 。信號的名稱在頭文件信號的名稱在頭文件signal.h中定義,均以中定義,均以SIG開頭。開頭。5.4 信號 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列19信號種類信號種類
26、下表中的信號未安排捕獲時,進程會立刻終止,并生成核心轉(zhuǎn)儲文件下表中的信號未安排捕獲時,進程會立刻終止,并生成核心轉(zhuǎn)儲文件core。5.4 信號信號名稱信號名稱說明說明SIGABORT*進程異常終止SIGALRM超時。一般由alarm設(shè)置的定時器產(chǎn)生。SIGFPE*浮點運算異常SIGHUP終端關(guān)閉或斷開連接。由處于非連接狀態(tài)的終端發(fā)給控制進程或由控制進程在自身結(jié)束時發(fā)給每個前臺進程。SIGILL*非法指令。通常由一個崩潰的程序或無效的共享內(nèi)存模塊引起。SIGINT程序終止,一般由從終端敲入的中斷字符(Ctrl + C)產(chǎn)生。SIGKILL終止進程(此信號不能被捕獲或忽略),一般在shell中用它
27、來強制終止異常進程。SIGPIPE向管道寫數(shù)據(jù)時沒有與之對應的讀進程時產(chǎn)生。SIGQUIT程序退出。一般由終端敲入的退出字符(Ctrl + )產(chǎn)生。SIGSEGV*無效內(nèi)存段訪問。一般是因為對內(nèi)存中的無效地址進行讀寫引起,如數(shù)組越界、解引用無效指針。SIGTERMkill命令默認發(fā)送的信號,要求進程結(jié)束運行。UNIX在關(guān)機時也用此信號要求服務(wù)停止運行。SIGUSR1用戶定義信號1,用于進程間通信SIGUSR2用戶定義信號2 ,用于進程間通信 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列20信號種類信號種類其它常見信號。其它常見信號。5.4 信號信號名稱信號名
28、稱說明說明SIGCHLD子進程停止或退出時產(chǎn)生,默認被忽略SIGCONT如果進程被暫停則繼續(xù)執(zhí)行。SIGSTOP停止執(zhí)行(此信號不能被捕獲或忽略)SIGTSTP終端掛起。通常因按下Ctrl + Z 組合鍵而產(chǎn)生。SIGTTIN后臺進程嘗試讀操作。shell用以表明后臺進程因需要從終端讀取輸入而暫停運行。SIGTTOU后臺進程嘗試寫操作。shell用以表明后臺進程因需要產(chǎn)生輸出而暫停運行。在命令行使用:在命令行使用:kill - ,可以向,可以向PID進程發(fā)送指定信號。進程發(fā)送指定信號。u如:如:kill HUP 512在命令行使用:在命令行使用:killall - ,可以向所有運行,可以向所有
29、運行的進程發(fā)送指定信號。的進程發(fā)送指定信號。u如:如:killall HUP inetd Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列21捕獲信號捕獲信號在程序中可以調(diào)用在程序中可以調(diào)用signal函數(shù)來捕獲信號。函數(shù)來捕獲信號。5.4 信號說明說明usig準備捕獲或忽略的信號。準備捕獲或忽略的信號。ufunc捕獲到信號后將要調(diào)用的回調(diào)函數(shù)。可以設(shè)為以下特殊值:捕獲到信號后將要調(diào)用的回調(diào)函數(shù)。可以設(shè)為以下特殊值:SIG_IGN忽略信號SIG_DFL恢復默認行為u返回值返回值成功時返回原先定義信號處理函數(shù),如果原先未定義則返回成功時返回原先定義信號處理函數(shù),如
30、果原先未定義則返回SIG_ERR,并設(shè)置并設(shè)置errno為一正數(shù)值;如給出的是一個無效的為一正數(shù)值;如給出的是一個無效的信號或不可捕獲或不可忽略的信號,則返回信號或不可捕獲或不可忽略的信號,則返回SIG_ERR,并設(shè)并設(shè)置置errno為為EINVAL。u注意:注意:回調(diào)函數(shù)中捕獲到一次信號后,對相應的信號的處理方式會自動恢復回調(diào)函數(shù)中捕獲到一次信號后,對相應的信號的處理方式會自動恢復到默認行為。到默認行為。#include void (*signal(int sig, void (*func)(int)(int);#include typedef void (*CALLBACK)(int);C
31、ALLBACK signal(int sig, CALLBACK func); Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列22捕獲信號捕獲信號示例示例5.4 信號#include #include #include void ouch(int sig) printf(“OUCH! - I got signal %dn”, sig); (void) signal(SIGINT, SIG_DFL);int main() (void) signal(SIGINT, ouch); while(1) printf(“Hello World!n”); sleep(1)
32、; 運行結(jié)果運行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列23發(fā)送信號發(fā)送信號進程可以通過進程可以通過kill系統(tǒng)調(diào)用向包括自身在內(nèi)的進程發(fā)送一個信號。系統(tǒng)調(diào)用向包括自身在內(nèi)的進程發(fā)送一個信號。5.4 信號說明說明upid接收信號的進程接收信號的進程PID。usig要發(fā)送的信號。要發(fā)送的信號。u返回值返回值成功時返回成功時返回0;失敗時返回;失敗時返回-1,并設(shè)置,并設(shè)置errno變量。變量。EINVAL給定的信號無效EPERM發(fā)送進程權(quán)限不夠ESRCH目標進程不存在u注:注:發(fā)送信號的進程應具有相應的權(quán)限。一般而言,兩個進程應擁有相同的發(fā)送信號的進
33、程應具有相應的權(quán)限。一般而言,兩個進程應擁有相同的UID(即只能發(fā)送信號給屬于自己的進程),但超級用戶可以發(fā)送信號給任(即只能發(fā)送信號給屬于自己的進程),但超級用戶可以發(fā)送信號給任何進程。何進程。#include #include int kill(pid_t pid, int sig); Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列24發(fā)送信號發(fā)送信號進程可以通過進程可以通過alarm函數(shù)在經(jīng)過一定時間后發(fā)送一個函數(shù)在經(jīng)過一定時間后發(fā)送一個SIGALRM信號,信號,即設(shè)置一個鬧鐘(定時器)。即設(shè)置一個鬧鐘(定時器)。5.4 信號說明說明useconds指定
34、幾秒后發(fā)送指定幾秒后發(fā)送SIGALRM信號,信號,0表示取消設(shè)置。表示取消設(shè)置。u返回值返回值成功時返回以前設(shè)置的鬧鐘時間的余留秒數(shù);失敗時返回成功時返回以前設(shè)置的鬧鐘時間的余留秒數(shù);失敗時返回0。u注:注:在接收到在接收到SIGALRM信號之前再次調(diào)用信號之前再次調(diào)用alarm函數(shù),鬧鐘會重新開始計時。函數(shù),鬧鐘會重新開始計時。#include unsigned alarm(unsigned seconds); Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列25sigaction系統(tǒng)調(diào)用系統(tǒng)調(diào)用在在Linux中,提供了一個比中,提供了一個比signal更健壯
35、的用于捕獲信號的編程接口:更健壯的用于捕獲信號的編程接口:sigaction。5.4 信號#include int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact);說明說明usig準備捕獲或忽略的信號。準備捕獲或忽略的信號。uact將要設(shè)置的信號處理動作。將要設(shè)置的信號處理動作。uoldact用于取回原先的信號處理動作。用于取回原先的信號處理動作。u返回值返回值成功時返回成功時返回0;失敗時返回;失敗時返回-1,并設(shè)置并設(shè)置errno變量,如給出的變量,如給出的是一個無效的信號或不可捕獲或不可忽
36、略的信號,是一個無效的信號或不可捕獲或不可忽略的信號,errno為為EINVAL 。u注:注:和和signal不一樣,由不一樣,由sigaction設(shè)置的信號處理函數(shù)默認是不被重置的。設(shè)置的信號處理函數(shù)默認是不被重置的。如果需要自動重置,應在如果需要自動重置,應在sa_flags成員中包含值成員中包含值SA_RESETHAND。struct sigaction void (*sa_handler)(int); / 信號處理函數(shù),同信號處理函數(shù),同signal sigset_t sa_mask; / 回調(diào)過程中將被屏蔽的信號集回調(diào)過程中將被屏蔽的信號集 int sa_flags; / 可決定回調(diào)
37、行為的位標志值可決定回調(diào)行為的位標志值 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列26sigaction系統(tǒng)調(diào)用系統(tǒng)調(diào)用示例示例5.4 信號#include #include #include void ouch(int sig) printf(“OUCH! - I got signal %dn”, sig);int main() struct sigaction act; act.sa_handler = ouch; sigemptyset(&act.sa_mask); act.sa_flags = 0; sigaction(SIGINT, &a
38、mp;act, 0); while(1) printf(“Hello World!n”); sleep(1); 運行結(jié)果運行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列27信號集信號集在頭文件在頭文件signal.h中定義了類型中定義了類型sigset_t和用來處理信號集的函數(shù)。和用來處理信號集的函數(shù)。5.4 信號#include int sigemptyset(sigset_t *set);int sigfillset(sigset_t *set);int sigaddset(sigset_t *set, int sig);int sigdelset
39、(sigset_t *set, int sig);int sigismember(const sigset_t *set, int sig);說明說明uset信號集信號集usig信號。信號。u返回值返回值失敗時返回失敗時返回-1,并設(shè)置并設(shè)置errno變量,只有一個錯誤代碼變量,只有一個錯誤代碼EINVAL,表示給定的信號無效。成功時,表示給定的信號無效。成功時,sigismeber函數(shù)函數(shù)返回返回1或或0;其他函數(shù)返回;其他函數(shù)返回0。typedef struct unsigned long sig_NSIG_WORDS; sigset_t; Unix/Linux程序環(huán)境 第第5章章進程、信
40、號和消息隊列進程、信號和消息隊列28概述概述消息隊列(消息隊列(message queues)是)是Linux中的一種中的一種IPC(Inter-Process Communication)機制。)機制。消息隊列提供了一種在兩個不相關(guān)的進程間傳遞數(shù)據(jù)的有效方法。消息隊列提供了一種在兩個不相關(guān)的進程間傳遞數(shù)據(jù)的有效方法。消息隊列獨立于發(fā)送和接收進程而存在。消息隊列獨立于發(fā)送和接收進程而存在。使用消息隊列可以從一個進程向另一個進程發(fā)送數(shù)據(jù)塊。每個數(shù)據(jù)塊使用消息隊列可以從一個進程向另一個進程發(fā)送數(shù)據(jù)塊。每個數(shù)據(jù)塊有一個最大長度的限制,系統(tǒng)中所有隊列所包含的全部數(shù)據(jù)塊的總長有一個最大長度的限制,系統(tǒng)中
41、所有隊列所包含的全部數(shù)據(jù)塊的總長度也有一個上限值。度也有一個上限值。Linux中有兩個宏定義中有兩個宏定義MSGMAX和和MSGMNB,它們分別定義了一條,它們分別定義了一條消息的最大長度和一個隊列的最大長度。消息的最大長度和一個隊列的最大長度。5.5 消息隊列 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列29msgget函數(shù)函數(shù)可以通過可以通過msgget系統(tǒng)調(diào)用創(chuàng)建或獲取一個消息隊列。系統(tǒng)調(diào)用創(chuàng)建或獲取一個消息隊列。說明說明ukey一個整數(shù)值,用于標識一個消息隊列。一個整數(shù)值,用于標識一個消息隊列。umsgflg一組標志。低端的九個一組標志。低端的九個b
42、it對應九種訪問權(quán)限,如對應九種訪問權(quán)限,如open系統(tǒng)系統(tǒng)調(diào)用。此外,可以和調(diào)用。此外,可以和IPC_CREAT按位或以創(chuàng)建一個新的消按位或以創(chuàng)建一個新的消息隊列。息隊列。u返回值返回值成功時返回一個正整數(shù),即消息隊列標識符;失敗時返回成功時返回一個正整數(shù),即消息隊列標識符;失敗時返回-1,并設(shè)置并設(shè)置errno變量。變量。u注:注:使用使用IPC_CREAT標志,當消息隊列已存在時,只是忽略創(chuàng)建動作,而不標志,當消息隊列已存在時,只是忽略創(chuàng)建動作,而不會出錯。會出錯。#include #include #include int msgget(key_t key, int msgflg);5
43、.5 消息隊列 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列30msgsnd函數(shù)函數(shù)可以通過可以通過msgsnd系統(tǒng)調(diào)用把一條消息添加到消息隊列中。系統(tǒng)調(diào)用把一條消息添加到消息隊列中。說明說明umsgid由由msgget返回的消息隊列標識符。返回的消息隊列標識符。umsgp指向要發(fā)送的消息的指針。指向要發(fā)送的消息的指針。umsgsz消息長度。這個長度不包括長整形成員變量的長度。消息長度。這個長度不包括長整形成員變量的長度。umsgflg標志。指定標志。指定IPC_NOWAIT時,表示當隊列滿或達到系統(tǒng)限制時,表示當隊列滿或達到系統(tǒng)限制時,函數(shù)立即返回(返回值
44、為時,函數(shù)立即返回(返回值為-1 ),不發(fā)送消息。),不發(fā)送消息。u返回值返回值成功時返回成功時返回0;失敗時返回;失敗時返回-1,并設(shè)置,并設(shè)置errno變量。變量。u注:注:消息的結(jié)構(gòu)受兩方面的約束:消息的結(jié)構(gòu)受兩方面的約束:長度必須小于系統(tǒng)規(guī)定的上限。必須以一個長整型成員變量開始,接收函數(shù)以此成員來確定消息的類型。#include #include #include int msgsnd(int msqid, const void *msgptr, size_t msgsz, int msgflg);5.5 消息隊列struct my_message long int message_t
45、ype; /* The data you wish to transfer */; Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列31msgrcv函數(shù)函數(shù)可以通過可以通過msgrcv系統(tǒng)調(diào)用從一個消息隊列獲取消息。系統(tǒng)調(diào)用從一個消息隊列獲取消息。說明說明umsgid由由msgget返回的消息隊列標識符。返回的消息隊列標識符。umsgp指向準備接收消息的指針。指向準備接收消息的指針。umsgsz消息長度。這個長度不包括長整形成員變量的長度。消息長度。這個長度不包括長整形成員變量的長度。umsgtyp一個長整數(shù)。若值為一個長整數(shù)。若值為0,獲取隊列中的第一個可用消
46、息;若值,獲取隊列中的第一個可用消息;若值大于大于0,獲取具有相同類型的第一個消息;若小于,獲取具有相同類型的第一個消息;若小于0,獲取消息,獲取消息類型小于或等于其絕對值的第一個消息。類型小于或等于其絕對值的第一個消息。umsgflg標志。指定標志。指定IPC_NOWAIT時,表示當中沒有相應類型消息時,表示當中沒有相應類型消息時,函數(shù)立即返回(返回值為時,函數(shù)立即返回(返回值為-1 ),不接收消息。),不接收消息。u返回值返回值成功時返回成功時返回0;失敗時返回;失敗時返回-1,并設(shè)置,并設(shè)置errno變量。變量。#include #include #include ssize_t msg
47、rcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);5.5 消息隊列 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列32msgctl函數(shù)函數(shù)可以通過可以通過msgctl系統(tǒng)調(diào)用直接控制消息隊列。系統(tǒng)調(diào)用直接控制消息隊列。說明說明umsgid由由msgget返回的消息隊列標識符。返回的消息隊列標識符。ucmd要采取的動作。要采取的動作。IPC_WAIT把msqid_ds結(jié)構(gòu)中的數(shù)據(jù)設(shè)置為消息隊列的當前關(guān)聯(lián)值。IPC_SET如果進程有足夠的權(quán)限,就把消息隊列的當前關(guān)聯(lián)值設(shè)置為msgqi
48、d_ds結(jié)構(gòu)中給出的值。IPC_RMID 刪除消息隊列。ubuf緩沖區(qū),作用視緩沖區(qū),作用視cmd而定。而定。u返回值返回值成功時返回成功時返回0;失敗時返回;失敗時返回-1,并設(shè)置,并設(shè)置errno變量。如果在進變量。如果在進程正阻塞于程正阻塞于msgsnd或或msgrcv中等待時刪除消息隊列,則這中等待時刪除消息隊列,則這兩個函數(shù)將失敗。兩個函數(shù)將失敗。#include #include #include int msgctl(int msqid, int cmd, struct msqid_ds *buf);5.5 消息隊列struct msqid_ds uid_t msg_perm.u
49、id; uid_t msg_perm.gid mode_t msg_perm.mode; Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列33/* 接收程序接收程序. msg1.c */#include #include #include #include #include #include struct my_msg_st long int my_msg_type; char some_textBUFSIZ;int main() int running = 1; int msgid; struct my_msg_st some_data; long int m
50、sg_to_receive = 0; /* 建立消息隊列建立消息隊列 */ msgid = msgget(key_t)1234, 0666 | IPC_CREAT); 綜合綜合示例示例5.5 消息隊列 Unix/Linux程序環(huán)境 第第5章章進程、信號和消息隊列進程、信號和消息隊列34綜合綜合示例示例5.5 消息隊列 if (msgid = -1) fprintf(stderr, msgget failed with error: %dn, errno); exit(EXIT_FAILURE); while(running) /*接收消息接收消息*/ if (msgrcv(msgid, (void *)&some_data, BUFSIZ, msg_to_receive, 0) = -1) fprintf(stderr, msgrcv failed with error: %dn, errno); exit(EXIT_FAILURE); printf(You wrote: %s, some_data.s
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度儲煤場煤炭交易代理服務(wù)合同3篇
- 2025年度金融機構(gòu)外匯借款合同綠色金融創(chuàng)新實踐
- 二零二五年度碼頭租賃項目環(huán)保驗收及服務(wù)合同4篇
- 二零二五年度錄音系統(tǒng)定制開發(fā)與實施合同3篇
- 2025年度蘋果水果產(chǎn)地直供直銷采購合同4篇
- 2025版木工模板租賃與園林景觀設(shè)計施工承包合同范本3篇
- 二零二五年度寵物醫(yī)院寵物食品研發(fā)與生產(chǎn)合作協(xié)議3篇
- 二零二五年度辦公家具銷售合同(含安裝)2篇
- 二零二五年度天使投資協(xié)議書:生物科技研發(fā)項目風險投資合同
- 二零二五年度商標授權(quán)及商標市場推廣合同范本2篇
- 2024-2030年中國招標代理行業(yè)深度分析及發(fā)展前景與發(fā)展戰(zhàn)略研究報告
- 醫(yī)師定期考核 (公共衛(wèi)生)試題庫500題(含答案)
- 基因突變和基因重組(第1課時)高一下學期生物人教版(2019)必修2
- 內(nèi)科學(醫(yī)學高級):風濕性疾病試題及答案(強化練習)
- 音樂劇好看智慧樹知到期末考試答案2024年
- 辦公設(shè)備(電腦、一體機、投影機等)采購 投標方案(技術(shù)方案)
- 案卷評查培訓課件模板
- 2024年江蘇省樣卷五年級數(shù)學上冊期末試卷及答案
- 人教版初中英語七八九全部單詞(打印版)
- 波浪理論要點圖解完美版
- 金融交易數(shù)據(jù)分析與風險評估項目環(huán)境敏感性分析
評論
0/150
提交評論