Linux第5章進(jìn)程、信號和消息隊(duì)列_第1頁
Linux第5章進(jìn)程、信號和消息隊(duì)列_第2頁
Linux第5章進(jìn)程、信號和消息隊(duì)列_第3頁
Linux第5章進(jìn)程、信號和消息隊(duì)列_第4頁
Linux第5章進(jìn)程、信號和消息隊(duì)列_第5頁
已閱讀5頁,還剩34頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第五章第五章 進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列1 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列25.1 什么是進(jìn)程“一個(gè)其中運(yùn)行著一個(gè)或多個(gè)線程的地址空間和這些線一個(gè)其中運(yùn)行著一個(gè)或多個(gè)線程的地址空間和這些線程所需要的系統(tǒng)資源。程所需要的系統(tǒng)資源?!薄罢谶\(yùn)行的程序。正在運(yùn)行的程序?!边M(jìn)程由程序代碼、數(shù)據(jù)、變量(占用著系統(tǒng)內(nèi)存)、打進(jìn)程由程序代碼、數(shù)據(jù)、變量(占用著系統(tǒng)內(nèi)存)、打開的文件(文件描述符)和環(huán)境組成。開的文件(文件描述符)和環(huán)境組成。 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列35.2 進(jìn)程的結(jié)構(gòu)多進(jìn)

2、程的管理方式多進(jìn)程的管理方式示例:兩個(gè)用戶同時(shí)運(yùn)行示例:兩個(gè)用戶同時(shí)運(yùn)行g(shù)rep程序程序搜索結(jié)束之前運(yùn)行搜索結(jié)束之前運(yùn)行ps命令命令 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列45.2 進(jìn)程的結(jié)構(gòu)多進(jìn)程的管理方式多進(jìn)程的管理方式示例:兩個(gè)用戶同時(shí)運(yùn)行示例:兩個(gè)用戶同時(shí)運(yùn)行g(shù)rep程序程序搜索結(jié)束之前運(yùn)行搜索結(jié)束之前運(yùn)行ps命令命令 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列55.2 進(jìn)程的結(jié)構(gòu)進(jìn)程表進(jìn)程表Linux進(jìn)程表是一個(gè)數(shù)據(jù)結(jié)構(gòu),其中保存了當(dāng)前所有進(jìn)程的相進(jìn)程表是一個(gè)數(shù)據(jù)結(jié)構(gòu),其中保存了當(dāng)前所有進(jìn)程的相關(guān)信息,包

3、括關(guān)信息,包括PID、狀態(tài)、命令字符串等(參見、狀態(tài)、命令字符串等(參見ps命令輸出命令輸出項(xiàng))。項(xiàng))。操作系統(tǒng)通過操作系統(tǒng)通過PID對進(jìn)程進(jìn)行管理,對進(jìn)程進(jìn)行管理,PID是進(jìn)程表的索引。是進(jìn)程表的索引。系統(tǒng)可同時(shí)運(yùn)行的進(jìn)程數(shù)只與可用于建立進(jìn)程表項(xiàng)的內(nèi)存容量系統(tǒng)可同時(shí)運(yùn)行的進(jìn)程數(shù)只與可用于建立進(jìn)程表項(xiàng)的內(nèi)存容量有關(guān)。有關(guān)。父進(jìn)程與子進(jìn)程父進(jìn)程與子進(jìn)程Linux啟動(dòng)時(shí)運(yùn)行一個(gè)名為啟動(dòng)時(shí)運(yùn)行一個(gè)名為init的進(jìn)程,該進(jìn)程是系統(tǒng)運(yùn)行的第的進(jìn)程,該進(jìn)程是系統(tǒng)運(yùn)行的第一個(gè)進(jìn)程,它的一個(gè)進(jìn)程,它的PID為為1。一般進(jìn)程一般進(jìn)程(除除init外外)都是由一個(gè)都是由一個(gè)“父進(jìn)程父進(jìn)程”創(chuàng)建的,被父進(jìn)程創(chuàng)創(chuàng)建的

4、,被父進(jìn)程創(chuàng)建的進(jìn)程稱為建的進(jìn)程稱為“子進(jìn)程子進(jìn)程”,init進(jìn)程是其他所有進(jìn)程的祖先進(jìn)程。進(jìn)程是其他所有進(jìn)程的祖先進(jìn)程。 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列65.2 進(jìn)程的結(jié)構(gòu)進(jìn)程狀態(tài)進(jìn)程狀態(tài)STATSTAT代碼代碼說明說明S S睡眠。通常是在等待某個(gè)事件的發(fā)生。睡眠。通常是在等待某個(gè)事件的發(fā)生。R R運(yùn)行運(yùn)行/ /可運(yùn)行。即在運(yùn)行隊(duì)列中,處于正在運(yùn)行或即將運(yùn)行狀態(tài)??蛇\(yùn)行。即在運(yùn)行隊(duì)列中,處于正在運(yùn)行或即將運(yùn)行狀態(tài)。D D不可中斷的睡眠(等待)。通常是在等待輸入或輸出完成。不可中斷的睡眠(等待)。通常是在等待輸入或輸出完成。T T停止。通常是被

5、停止。通常是被shellshell作業(yè)控制所停止,或處于調(diào)試器控制下。作業(yè)控制所停止,或處于調(diào)試器控制下。Z Z僵尸(僵尸(zombiezombie)進(jìn)程。)進(jìn)程。N N低優(yōu)先級任務(wù)。低優(yōu)先級任務(wù)。s s進(jìn)程是會話期首進(jìn)程。進(jìn)程是會話期首進(jìn)程。+ +進(jìn)程屬于前臺進(jìn)程組。進(jìn)程屬于前臺進(jìn)程組。l l進(jìn)程是多線程的。進(jìn)程是多線程的。 高優(yōu)先級任務(wù)。高優(yōu)先級任務(wù)。 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列7system函數(shù)函數(shù)可以調(diào)用標(biāo)準(zhǔn)庫函數(shù)可以調(diào)用標(biāo)準(zhǔn)庫函數(shù)system在程序內(nèi)啟動(dòng)另一個(gè)程序,從而創(chuàng)在程序內(nèi)啟動(dòng)另一個(gè)程序,從而創(chuàng)建一個(gè)新進(jìn)程。建一個(gè)新進(jìn)程。#

6、include int system(const char *command);說明說明ucommand待運(yùn)行的程序(命令字符串)。待運(yùn)行的程序(命令字符串)。u返回值返回值無法啟動(dòng)無法啟動(dòng)shell時(shí),返回時(shí),返回127;其它錯(cuò)誤時(shí)返回其它錯(cuò)誤時(shí)返回-1;否;否則,返回命令的退出碼。則,返回命令的退出碼。usystem函數(shù)運(yùn)行函數(shù)運(yùn)行command命令并等待該命令完成,本質(zhì)是調(diào)用:命令并等待該命令完成,本質(zhì)是調(diào)用:/bin/sh c command。u注:注:使用使用system函數(shù)并非啟動(dòng)其他進(jìn)程的理想手段,因其必須先函數(shù)并非啟動(dòng)其他進(jìn)程的理想手段,因其必須先啟動(dòng)一個(gè)啟動(dòng)一個(gè)shell,再

7、使用該,再使用該shell執(zhí)行相應(yīng)的命令。執(zhí)行相應(yīng)的命令。5.3 創(chuàng)建進(jìn)程 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列85.3 創(chuàng)建進(jìn)程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章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列9替換進(jìn)程映像替換進(jìn)程映像可以調(diào)用可以調(diào)用exec系列函數(shù)把當(dāng)前進(jìn)程替換為一個(gè)新進(jìn)程。系列函數(shù)把當(dāng)前進(jìn)程替換為一

8、個(gè)新進(jìn)程。#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待運(yùn)行的程序全路徑名(命令字符串)。待運(yùn)行的程序全路徑名(命令字符串)。ufile待運(yùn)行的程序名,通過待運(yùn)行的程序名,通過PATH環(huán)境變量搜索其路徑。環(huán)境變量搜索其路徑。uarg命令參數(shù)。命令參數(shù)。uargv命令參數(shù)。命令參數(shù)。uenvp傳遞給待運(yùn)行程序的環(huán)境變量。傳遞給待運(yùn)行程序的環(huán)境變量。u返回值返回值成功時(shí)不返回(原程序不再執(zhí)行)成功時(shí)不返回(原程序不再執(zhí)行);出錯(cuò)時(shí)返回出錯(cuò)時(shí)返回-1,并設(shè)置,并設(shè)置errno變量。變量。5.3 創(chuàng)建進(jìn)程 Unix

10、/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列105.3 創(chuàng)建進(jìn)程替換進(jìn)程映像替換進(jìn)程映像用法用法#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章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列115.3 創(chuàng)建進(jìn)程替換進(jìn)程映像替換進(jìn)程映像示例示例#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新進(jìn)程的新進(jìn)程的PID、PPID及及nice值和原先的完全一樣。值和原先的

13、完全一樣。uexec系列函數(shù)啟動(dòng)的新進(jìn)程的參數(shù)表和環(huán)境變量的總長度是有限制的。上系列函數(shù)啟動(dòng)的新進(jìn)程的參數(shù)表和環(huán)境變量的總長度是有限制的。上限由限由ARG_MAX給出,給出, POSIX規(guī)定至少為規(guī)定至少為4KB,Linux中為中為128KB。u原進(jìn)程中已打開的文件描述符在新進(jìn)程中仍保持打開(除非原進(jìn)程中已打開的文件描述符在新進(jìn)程中仍保持打開(除非“執(zhí)行時(shí)關(guān)閉執(zhí)行時(shí)關(guān)閉標(biāo)志標(biāo)志”被置位)。被置位)。u原進(jìn)程中打開的目錄流在新進(jìn)程中被關(guān)閉。原進(jìn)程中打開的目錄流在新進(jìn)程中被關(guān)閉。 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列12復(fù)制進(jìn)程映像復(fù)制進(jìn)程映像可以調(diào)用可

14、以調(diào)用fork函數(shù)創(chuàng)建一個(gè)新進(jìn)程。函數(shù)創(chuàng)建一個(gè)新進(jìn)程。#include pid_t fork(void);說明說明u返回值返回值成功時(shí),父進(jìn)程中返回子進(jìn)程的成功時(shí),父進(jìn)程中返回子進(jìn)程的PID,子進(jìn)程中返回,子進(jìn)程中返回0; 失失敗時(shí)返回?cái)r(shí)返回-1,并設(shè)置,并設(shè)置errno變量。變量。ufork系統(tǒng)調(diào)用復(fù)制當(dāng)前進(jìn)程,在進(jìn)程表中添加一個(gè)新的表項(xiàng),新表項(xiàng)的多系統(tǒng)調(diào)用復(fù)制當(dāng)前進(jìn)程,在進(jìn)程表中添加一個(gè)新的表項(xiàng),新表項(xiàng)的多數(shù)屬性與當(dāng)前進(jìn)程相同。數(shù)屬性與當(dāng)前進(jìn)程相同。u新進(jìn)程與原進(jìn)程執(zhí)行的代碼完全相同,但新進(jìn)程有自己的數(shù)據(jù)空間、環(huán)境新進(jìn)程與原進(jìn)程執(zhí)行的代碼完全相同,但新進(jìn)程有自己的數(shù)據(jù)空間、環(huán)境和文件描述

15、符。和文件描述符。u通常,使用通常,使用fork和和exec系列函數(shù)一起創(chuàng)建多進(jìn)程環(huán)境。系列函數(shù)一起創(chuàng)建多進(jìn)程環(huán)境。u典型的典型的fork代碼。代碼。5.3 創(chuàng)建進(jìn)程典型錯(cuò)誤為典型錯(cuò)誤為E_AGAIN子進(jìn)程超過子進(jìn)程超過CHILD_MAX限制限制ENOMEM進(jìn)程表無足夠空間進(jìn)程表無足夠空間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章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列13復(fù)制進(jìn)程映像復(fù)制進(jìn)程映像示例示例5.3 創(chuàng)建進(jìn)程#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);運(yùn)行結(jié)果運(yùn)行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列14等待進(jìn)程等待進(jìn)程在父進(jìn)程中調(diào)用在父進(jìn)程中調(diào)用wait函數(shù)可以讓父進(jìn)程等待任一子進(jìn)程的結(jié)束。函數(shù)可以讓父進(jìn)程等待任一子進(jìn)程的結(jié)束。#include #include pid_t wait(int *status);說明說明ustatus輸出參數(shù),用于獲取子進(jìn)程的退出狀態(tài)。輸出參數(shù),用于獲取子進(jìn)程的退出狀態(tài)。

18、u返回值返回值成功時(shí),返回已結(jié)束子進(jìn)程的成功時(shí),返回已結(jié)束子進(jìn)程的PID;出錯(cuò)時(shí)返回;出錯(cuò)時(shí)返回-1,并設(shè)置,并設(shè)置errno變量。變量。u以下宏可用于解釋子進(jìn)程退出狀態(tài)信息。以下宏可用于解釋子進(jìn)程退出狀態(tài)信息。5.3 創(chuàng)建進(jìn)程宏宏 說明說明WIFEXITED(status) 如果子進(jìn)程正常結(jié)束,則取非零值。WEXITSTATUS(status) 如果WIFEXITED非零,則得到子進(jìn)程的退出碼。WIFSIGNALED(status) 如果子進(jìn)程因未捕獲的信號而終止,則取非零值。WTERMSIG(status) 如果WIFSIGNALED非零, 則得到引起子進(jìn)程終止的信號代碼。WIFSTOPP

19、ED(status) 如果子進(jìn)程已意外終止,則取非零值。WSTOPSIG(status) 如果WIFSTOPPED非零, 則得到引起子進(jìn)程終止的信號代碼。 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列15等待進(jìn)程等待進(jìn)程在父進(jìn)程中調(diào)用在父進(jìn)程中調(diào)用waitpid函數(shù)可以讓父進(jìn)程等待指定的子進(jìn)程的結(jié)束。函數(shù)可以讓父進(jìn)程等待指定的子進(jìn)程的結(jié)束。#include #include pid_t waitpid(pid_t pid, int *status, int options);說明說明upid要等待的子進(jìn)程的要等待的子進(jìn)程的PID,值為,值為-1時(shí)意為任一子進(jìn)

20、程。時(shí)意為任一子進(jìn)程。ustatus輸出參數(shù),用于獲取子進(jìn)程的退出狀態(tài)。輸出參數(shù),用于獲取子進(jìn)程的退出狀態(tài)。uoptions常見的選項(xiàng)為常見的選項(xiàng)為WNOHANG,意為不掛起調(diào)用者進(jìn)程。,意為不掛起調(diào)用者進(jìn)程。u返回值返回值成功時(shí),返回已結(jié)束子進(jìn)程的成功時(shí),返回已結(jié)束子進(jìn)程的PID;若指定了;若指定了WNOHANG選選項(xiàng),但沒有子進(jìn)程終止,則返回項(xiàng),但沒有子進(jìn)程終止,則返回0。出錯(cuò)時(shí)返回。出錯(cuò)時(shí)返回-1,并設(shè)置,并設(shè)置errno變量。變量。5.3 創(chuàng)建進(jìn)程若要周期性地檢查某個(gè)子進(jìn)程是否已終止,可以使用如下調(diào)用方式:若要周期性地檢查某個(gè)子進(jìn)程是否已終止,可以使用如下調(diào)用方式:waitpid(ch

21、ild_pid, (int *) 0, WNOHANG); Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列16等待進(jìn)程等待進(jìn)程示例示例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)建進(jìn)程 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);運(yùn)行結(jié)果運(yùn)行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列17僵尸進(jìn)程僵尸進(jìn)程子進(jìn)程終止時(shí),它與父進(jìn)程之間的關(guān)聯(lián)還會保持(進(jìn)程表中代表子進(jìn)子進(jìn)程終止時(shí),它與父進(jìn)程之間的關(guān)聯(lián)還會保持(進(jìn)程表中代表子進(jìn)程的表項(xiàng)不會立刻釋放,其中含退出碼),直到父進(jìn)程也正常終止或程的表項(xiàng)不會立刻釋放,其中含退出碼),直到父進(jìn)程也正常終止或父進(jìn)程調(diào)用了父進(jìn)程調(diào)用了wait

24、或或waitpid函數(shù)。函數(shù)。已結(jié)束運(yùn)行但進(jìn)程表項(xiàng)仍存在的子進(jìn)程稱為已結(jié)束運(yùn)行但進(jìn)程表項(xiàng)仍存在的子進(jìn)程稱為“僵尸進(jìn)程僵尸進(jìn)程”。如果一個(gè)僵尸進(jìn)程的父進(jìn)程因異常而終止,該僵尸進(jìn)程將由如果一個(gè)僵尸進(jìn)程的父進(jìn)程因異常而終止,該僵尸進(jìn)程將由init進(jìn)程接進(jìn)程接管,它將一直保持在進(jìn)程表中直到被管,它將一直保持在進(jìn)程表中直到被init進(jìn)程發(fā)現(xiàn)并釋放。進(jìn)程發(fā)現(xiàn)并釋放。應(yīng)盡量避免產(chǎn)生僵尸進(jìn)程。應(yīng)盡量避免產(chǎn)生僵尸進(jìn)程。5.3 創(chuàng)建進(jìn)程 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列18概述概述信號是信號是UNIX和和Linux系統(tǒng)為響應(yīng)某些條件而產(chǎn)生的一個(gè)事件。系統(tǒng)為響應(yīng)某些條

25、件而產(chǎn)生的一個(gè)事件。信號一般是因某些錯(cuò)誤條件而產(chǎn)生的,如內(nèi)存段沖突、浮點(diǎn)處理器錯(cuò)信號一般是因某些錯(cuò)誤條件而產(chǎn)生的,如內(nèi)存段沖突、浮點(diǎn)處理器錯(cuò)誤或非法指令等。誤或非法指令等。信號可作為進(jìn)程間通信的一種機(jī)制,由一個(gè)進(jìn)程發(fā)送給另一個(gè)進(jìn)程。信號可作為進(jìn)程間通信的一種機(jī)制,由一個(gè)進(jìn)程發(fā)送給另一個(gè)進(jìn)程。信號可被生成、捕獲或響應(yīng),對于一些信號也可被忽略信號可被生成、捕獲或響應(yīng),對于一些信號也可被忽略 。信號的名稱在頭文件信號的名稱在頭文件signal.h中定義,均以中定義,均以SIG開頭。開頭。5.4 信號 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列19信號種類信號種類

26、下表中的信號未安排捕獲時(shí),進(jìn)程會立刻終止,并生成核心轉(zhuǎn)儲文件下表中的信號未安排捕獲時(shí),進(jìn)程會立刻終止,并生成核心轉(zhuǎn)儲文件core。5.4 信號信號名稱信號名稱說明說明SIGABORT*進(jìn)程異常終止SIGALRM超時(shí)。一般由alarm設(shè)置的定時(shí)器產(chǎn)生。SIGFPE*浮點(diǎn)運(yùn)算異常SIGHUP終端關(guān)閉或斷開連接。由處于非連接狀態(tài)的終端發(fā)給控制進(jìn)程或由控制進(jìn)程在自身結(jié)束時(shí)發(fā)給每個(gè)前臺進(jìn)程。SIGILL*非法指令。通常由一個(gè)崩潰的程序或無效的共享內(nèi)存模塊引起。SIGINT程序終止,一般由從終端敲入的中斷字符(Ctrl + C)產(chǎn)生。SIGKILL終止進(jìn)程(此信號不能被捕獲或忽略),一般在shell中用它

27、來強(qiáng)制終止異常進(jìn)程。SIGPIPE向管道寫數(shù)據(jù)時(shí)沒有與之對應(yīng)的讀進(jìn)程時(shí)產(chǎn)生。SIGQUIT程序退出。一般由終端敲入的退出字符(Ctrl + )產(chǎn)生。SIGSEGV*無效內(nèi)存段訪問。一般是因?yàn)閷?nèi)存中的無效地址進(jìn)行讀寫引起,如數(shù)組越界、解引用無效指針。SIGTERMkill命令默認(rèn)發(fā)送的信號,要求進(jìn)程結(jié)束運(yùn)行。UNIX在關(guān)機(jī)時(shí)也用此信號要求服務(wù)停止運(yùn)行。SIGUSR1用戶定義信號1,用于進(jìn)程間通信SIGUSR2用戶定義信號2 ,用于進(jìn)程間通信 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列20信號種類信號種類其它常見信號。其它常見信號。5.4 信號信號名稱信號名

28、稱說明說明SIGCHLD子進(jìn)程停止或退出時(shí)產(chǎn)生,默認(rèn)被忽略SIGCONT如果進(jìn)程被暫停則繼續(xù)執(zhí)行。SIGSTOP停止執(zhí)行(此信號不能被捕獲或忽略)SIGTSTP終端掛起。通常因按下Ctrl + Z 組合鍵而產(chǎn)生。SIGTTIN后臺進(jìn)程嘗試讀操作。shell用以表明后臺進(jìn)程因需要從終端讀取輸入而暫停運(yùn)行。SIGTTOU后臺進(jìn)程嘗試寫操作。shell用以表明后臺進(jìn)程因需要產(chǎn)生輸出而暫停運(yùn)行。在命令行使用:在命令行使用:kill - ,可以向,可以向PID進(jìn)程發(fā)送指定信號。進(jìn)程發(fā)送指定信號。u如:如:kill HUP 512在命令行使用:在命令行使用:killall - ,可以向所有運(yùn)行,可以向所有

29、運(yùn)行的進(jìn)程發(fā)送指定信號。的進(jìn)程發(fā)送指定信號。u如:如:killall HUP inetd Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列21捕獲信號捕獲信號在程序中可以調(diào)用在程序中可以調(diào)用signal函數(shù)來捕獲信號。函數(shù)來捕獲信號。5.4 信號說明說明usig準(zhǔn)備捕獲或忽略的信號。準(zhǔn)備捕獲或忽略的信號。ufunc捕獲到信號后將要調(diào)用的回調(diào)函數(shù)??梢栽O(shè)為以下特殊值:捕獲到信號后將要調(diào)用的回調(diào)函數(shù)??梢栽O(shè)為以下特殊值:SIG_IGN忽略信號SIG_DFL恢復(fù)默認(rèn)行為u返回值返回值成功時(shí)返回原先定義信號處理函數(shù),如果原先未定義則返回成功時(shí)返回原先定義信號處理函數(shù),如

30、果原先未定義則返回SIG_ERR,并設(shè)置并設(shè)置errno為一正數(shù)值;如給出的是一個(gè)無效的為一正數(shù)值;如給出的是一個(gè)無效的信號或不可捕獲或不可忽略的信號,則返回信號或不可捕獲或不可忽略的信號,則返回SIG_ERR,并設(shè)并設(shè)置置errno為為EINVAL。u注意:注意:回調(diào)函數(shù)中捕獲到一次信號后,對相應(yīng)的信號的處理方式會自動(dòng)恢復(fù)回調(diào)函數(shù)中捕獲到一次信號后,對相應(yīng)的信號的處理方式會自動(dòng)恢復(fù)到默認(rèn)行為。到默認(rèn)行為。#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章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列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、; 運(yùn)行結(jié)果運(yùn)行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列23發(fā)送信號發(fā)送信號進(jìn)程可以通過進(jìn)程可以通過kill系統(tǒng)調(diào)用向包括自身在內(nèi)的進(jìn)程發(fā)送一個(gè)信號。系統(tǒng)調(diào)用向包括自身在內(nèi)的進(jìn)程發(fā)送一個(gè)信號。5.4 信號說明說明upid接收信號的進(jìn)程接收信號的進(jìn)程PID。usig要發(fā)送的信號。要發(fā)送的信號。u返回值返回值成功時(shí)返回成功時(shí)返回0;失敗時(shí)返回;失敗時(shí)返回-1,并設(shè)置,并設(shè)置errno變量。變量。EINVAL給定的信號無效EPERM發(fā)送進(jìn)程權(quán)限不夠ESRCH目標(biāo)進(jìn)程不存在u注:注:發(fā)送信號的進(jìn)程應(yīng)具有相應(yīng)的權(quán)限。一般而言,兩個(gè)進(jìn)程應(yīng)擁有相同的發(fā)送信號的進(jìn)

33、程應(yīng)具有相應(yīng)的權(quán)限。一般而言,兩個(gè)進(jìn)程應(yīng)擁有相同的UID(即只能發(fā)送信號給屬于自己的進(jìn)程),但超級用戶可以發(fā)送信號給任(即只能發(fā)送信號給屬于自己的進(jìn)程),但超級用戶可以發(fā)送信號給任何進(jìn)程。何進(jìn)程。#include #include int kill(pid_t pid, int sig); Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列24發(fā)送信號發(fā)送信號進(jìn)程可以通過進(jìn)程可以通過alarm函數(shù)在經(jīng)過一定時(shí)間后發(fā)送一個(gè)函數(shù)在經(jīng)過一定時(shí)間后發(fā)送一個(gè)SIGALRM信號,信號,即設(shè)置一個(gè)鬧鐘(定時(shí)器)。即設(shè)置一個(gè)鬧鐘(定時(shí)器)。5.4 信號說明說明useconds指定

34、幾秒后發(fā)送指定幾秒后發(fā)送SIGALRM信號,信號,0表示取消設(shè)置。表示取消設(shè)置。u返回值返回值成功時(shí)返回以前設(shè)置的鬧鐘時(shí)間的余留秒數(shù);失敗時(shí)返回成功時(shí)返回以前設(shè)置的鬧鐘時(shí)間的余留秒數(shù);失敗時(shí)返回0。u注:注:在接收到在接收到SIGALRM信號之前再次調(diào)用信號之前再次調(diào)用alarm函數(shù),鬧鐘會重新開始計(jì)時(shí)。函數(shù),鬧鐘會重新開始計(jì)時(shí)。#include unsigned alarm(unsigned seconds); Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列25sigaction系統(tǒng)調(diào)用系統(tǒng)調(diào)用在在Linux中,提供了一個(gè)比中,提供了一個(gè)比signal更健壯

35、的用于捕獲信號的編程接口:更健壯的用于捕獲信號的編程接口:sigaction。5.4 信號#include int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact);說明說明usig準(zhǔn)備捕獲或忽略的信號。準(zhǔn)備捕獲或忽略的信號。uact將要設(shè)置的信號處理動(dòng)作。將要設(shè)置的信號處理動(dòng)作。uoldact用于取回原先的信號處理動(dòng)作。用于取回原先的信號處理動(dòng)作。u返回值返回值成功時(shí)返回成功時(shí)返回0;失敗時(shí)返回;失敗時(shí)返回-1,并設(shè)置并設(shè)置errno變量,如給出的變量,如給出的是一個(gè)無效的信號或不可捕獲或不可忽

36、略的信號,是一個(gè)無效的信號或不可捕獲或不可忽略的信號,errno為為EINVAL 。u注:注:和和signal不一樣,由不一樣,由sigaction設(shè)置的信號處理函數(shù)默認(rèn)是不被重置的。設(shè)置的信號處理函數(shù)默認(rèn)是不被重置的。如果需要自動(dòng)重置,應(yīng)在如果需要自動(dòng)重置,應(yīng)在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、行為的位標(biāo)志值可決定回調(diào)行為的位標(biāo)志值 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列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); 運(yùn)行結(jié)果運(yùn)行結(jié)果 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列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返回值返回值失敗時(shí)返回失敗時(shí)返回-1,并設(shè)置并設(shè)置errno變量,只有一個(gè)錯(cuò)誤代碼變量,只有一個(gè)錯(cuò)誤代碼EINVAL,表示給定的信號無效。成功時(shí),表示給定的信號無效。成功時(shí),sigismeber函數(shù)函數(shù)返回返回1或或0;其他函數(shù)返回;其他函數(shù)返回0。typedef struct unsigned long sig_NSIG_WORDS; sigset_t; Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信

40、號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列28概述概述消息隊(duì)列(消息隊(duì)列(message queues)是)是Linux中的一種中的一種IPC(Inter-Process Communication)機(jī)制。)機(jī)制。消息隊(duì)列提供了一種在兩個(gè)不相關(guān)的進(jìn)程間傳遞數(shù)據(jù)的有效方法。消息隊(duì)列提供了一種在兩個(gè)不相關(guān)的進(jìn)程間傳遞數(shù)據(jù)的有效方法。消息隊(duì)列獨(dú)立于發(fā)送和接收進(jìn)程而存在。消息隊(duì)列獨(dú)立于發(fā)送和接收進(jìn)程而存在。使用消息隊(duì)列可以從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送數(shù)據(jù)塊。每個(gè)數(shù)據(jù)塊使用消息隊(duì)列可以從一個(gè)進(jìn)程向另一個(gè)進(jìn)程發(fā)送數(shù)據(jù)塊。每個(gè)數(shù)據(jù)塊有一個(gè)最大長度的限制,系統(tǒng)中所有隊(duì)列所包含的全部數(shù)據(jù)塊的總長有一個(gè)最大長度的限制,系統(tǒng)中

41、所有隊(duì)列所包含的全部數(shù)據(jù)塊的總長度也有一個(gè)上限值。度也有一個(gè)上限值。Linux中有兩個(gè)宏定義中有兩個(gè)宏定義MSGMAX和和MSGMNB,它們分別定義了一條,它們分別定義了一條消息的最大長度和一個(gè)隊(duì)列的最大長度。消息的最大長度和一個(gè)隊(duì)列的最大長度。5.5 消息隊(duì)列 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列29msgget函數(shù)函數(shù)可以通過可以通過msgget系統(tǒng)調(diào)用創(chuàng)建或獲取一個(gè)消息隊(duì)列。系統(tǒng)調(diào)用創(chuàng)建或獲取一個(gè)消息隊(duì)列。說明說明ukey一個(gè)整數(shù)值,用于標(biāo)識一個(gè)消息隊(duì)列。一個(gè)整數(shù)值,用于標(biāo)識一個(gè)消息隊(duì)列。umsgflg一組標(biāo)志。低端的九個(gè)一組標(biāo)志。低端的九個(gè)b

42、it對應(yīng)九種訪問權(quán)限,如對應(yīng)九種訪問權(quán)限,如open系統(tǒng)系統(tǒng)調(diào)用。此外,可以和調(diào)用。此外,可以和IPC_CREAT按位或以創(chuàng)建一個(gè)新的消按位或以創(chuàng)建一個(gè)新的消息隊(duì)列。息隊(duì)列。u返回值返回值成功時(shí)返回一個(gè)正整數(shù),即消息隊(duì)列標(biāo)識符;失敗時(shí)返回成功時(shí)返回一個(gè)正整數(shù),即消息隊(duì)列標(biāo)識符;失敗時(shí)返回-1,并設(shè)置并設(shè)置errno變量。變量。u注:注:使用使用IPC_CREAT標(biāo)志,當(dāng)消息隊(duì)列已存在時(shí),只是忽略創(chuàng)建動(dòng)作,而不標(biāo)志,當(dāng)消息隊(duì)列已存在時(shí),只是忽略創(chuàng)建動(dòng)作,而不會出錯(cuò)。會出錯(cuò)。#include #include #include int msgget(key_t key, int msgflg);5

43、.5 消息隊(duì)列 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列30msgsnd函數(shù)函數(shù)可以通過可以通過msgsnd系統(tǒng)調(diào)用把一條消息添加到消息隊(duì)列中。系統(tǒng)調(diào)用把一條消息添加到消息隊(duì)列中。說明說明umsgid由由msgget返回的消息隊(duì)列標(biāo)識符。返回的消息隊(duì)列標(biāo)識符。umsgp指向要發(fā)送的消息的指針。指向要發(fā)送的消息的指針。umsgsz消息長度。這個(gè)長度不包括長整形成員變量的長度。消息長度。這個(gè)長度不包括長整形成員變量的長度。umsgflg標(biāo)志。指定標(biāo)志。指定IPC_NOWAIT時(shí),表示當(dāng)隊(duì)列滿或達(dá)到系統(tǒng)限制時(shí),表示當(dāng)隊(duì)列滿或達(dá)到系統(tǒng)限制時(shí),函數(shù)立即返回(返回值

44、為時(shí),函數(shù)立即返回(返回值為-1 ),不發(fā)送消息。),不發(fā)送消息。u返回值返回值成功時(shí)返回成功時(shí)返回0;失敗時(shí)返回;失敗時(shí)返回-1,并設(shè)置,并設(shè)置errno變量。變量。u注:注:消息的結(jié)構(gòu)受兩方面的約束:消息的結(jié)構(gòu)受兩方面的約束:長度必須小于系統(tǒng)規(guī)定的上限。必須以一個(gè)長整型成員變量開始,接收函數(shù)以此成員來確定消息的類型。#include #include #include int msgsnd(int msqid, const void *msgptr, size_t msgsz, int msgflg);5.5 消息隊(duì)列struct my_message long int message_t

45、ype; /* The data you wish to transfer */; Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列31msgrcv函數(shù)函數(shù)可以通過可以通過msgrcv系統(tǒng)調(diào)用從一個(gè)消息隊(duì)列獲取消息。系統(tǒng)調(diào)用從一個(gè)消息隊(duì)列獲取消息。說明說明umsgid由由msgget返回的消息隊(duì)列標(biāo)識符。返回的消息隊(duì)列標(biāo)識符。umsgp指向準(zhǔn)備接收消息的指針。指向準(zhǔn)備接收消息的指針。umsgsz消息長度。這個(gè)長度不包括長整形成員變量的長度。消息長度。這個(gè)長度不包括長整形成員變量的長度。umsgtyp一個(gè)長整數(shù)。若值為一個(gè)長整數(shù)。若值為0,獲取隊(duì)列中的第一個(gè)可用消

46、息;若值,獲取隊(duì)列中的第一個(gè)可用消息;若值大于大于0,獲取具有相同類型的第一個(gè)消息;若小于,獲取具有相同類型的第一個(gè)消息;若小于0,獲取消息,獲取消息類型小于或等于其絕對值的第一個(gè)消息。類型小于或等于其絕對值的第一個(gè)消息。umsgflg標(biāo)志。指定標(biāo)志。指定IPC_NOWAIT時(shí),表示當(dāng)中沒有相應(yīng)類型消息時(shí),表示當(dāng)中沒有相應(yīng)類型消息時(shí),函數(shù)立即返回(返回值為時(shí),函數(shù)立即返回(返回值為-1 ),不接收消息。),不接收消息。u返回值返回值成功時(shí)返回成功時(shí)返回0;失敗時(shí)返回;失敗時(shí)返回-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 消息隊(duì)列 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列32msgctl函數(shù)函數(shù)可以通過可以通過msgctl系統(tǒng)調(diào)用直接控制消息隊(duì)列。系統(tǒng)調(diào)用直接控制消息隊(duì)列。說明說明umsgid由由msgget返回的消息隊(duì)列標(biāo)識符。返回的消息隊(duì)列標(biāo)識符。ucmd要采取的動(dòng)作。要采取的動(dòng)作。IPC_WAIT把msqid_ds結(jié)構(gòu)中的數(shù)據(jù)設(shè)置為消息隊(duì)列的當(dāng)前關(guān)聯(lián)值。IPC_SET如果進(jìn)程有足夠的權(quán)限,就把消息隊(duì)列的當(dāng)前關(guān)聯(lián)值設(shè)置為msgqi

48、d_ds結(jié)構(gòu)中給出的值。IPC_RMID 刪除消息隊(duì)列。ubuf緩沖區(qū),作用視緩沖區(qū),作用視cmd而定。而定。u返回值返回值成功時(shí)返回成功時(shí)返回0;失敗時(shí)返回;失敗時(shí)返回-1,并設(shè)置,并設(shè)置errno變量。如果在進(jìn)變量。如果在進(jìn)程正阻塞于程正阻塞于msgsnd或或msgrcv中等待時(shí)刪除消息隊(duì)列,則這中等待時(shí)刪除消息隊(duì)列,則這兩個(gè)函數(shù)將失敗。兩個(gè)函數(shù)將失敗。#include #include #include int msgctl(int msqid, int cmd, struct msqid_ds *buf);5.5 消息隊(duì)列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章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列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; /* 建立消息隊(duì)列建立消息隊(duì)列 */ msgid = msgget(key_t)1234, 0666 | IPC_CREAT); 綜合綜合示例示例5.5 消息隊(duì)列 Unix/Linux程序環(huán)境 第第5章章進(jìn)程、信號和消息隊(duì)列進(jìn)程、信號和消息隊(duì)列34綜合綜合示例示例5.5 消息隊(duì)列 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)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論