进程间通信之信号he信号量
信號(hào)的篇幅較少,就把他和信號(hào)量放在一起了。先講講他們之間的區(qū)別:
1.信號(hào):(signal)是一種處理異步事件的方式。信號(hào)時(shí)比較復(fù)雜的通信方式,用于通知接受進(jìn)程有某種事件發(fā)生,除了用于進(jìn)程外,還可以發(fā)送信號(hào)給進(jìn)程本身。linux除了支持unix早期的信號(hào)語(yǔ)義函數(shù),還支持語(yǔ)義符合posix.1標(biāo)準(zhǔn)的信號(hào)函數(shù)sigaction。
2.信號(hào)量:(Semaphore)進(jìn)程間通信處理同步互斥的機(jī)制。是在多線程環(huán)境下使用的一種設(shè)施, 它負(fù)責(zé)協(xié)調(diào)各個(gè)線程, 以保證它們能夠正確、合理的使用公共資源。
信號(hào):
使用信號(hào)要先知道有哪些信號(hào),在Linux下有31個(gè)需要記住的通用信號(hào),篇幅限制,這里就不贅述了。
signal:
kill:
#include <stdio.h> #include <signal.h>int main() {//while (1){kill (pid, sig);sleep(1);}return 0; }alarm:
#include <stdio.h> #include <signal.h>// 信號(hào)處理函數(shù) void handle(int signum) {printf ("hello world\n");// 定時(shí)器重置alarm(2); }int main() {// 定時(shí)器是一次性的alarm(2);signal(SIGALRM, handle);while (1);return 0; }sigaction:
#include <stdio.h> #include <signal.h>// 信號(hào)處理函數(shù) void handle(int signum) {printf ("hello world\n");// 定時(shí)器重置alarm(2); }int main() {// 定時(shí)器是一次性的alarm(2);struct sigaction act;act.sa_handler = handle;sigaction(SIGALRM, &act, NULL);while (1);return 0; }處理子進(jìn)程的退出:
#include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/wait.h>// 信號(hào)處理函數(shù) void handle(int signum) {while (waitpid (-1, NULL, WNOHANG) > 0){printf ("捕獲一個(gè)子進(jìn)程\n");}printf ("111111\n"); }int main() {signal (SIGCHLD, handle);int count = 10;while (count--){pid_t pid = fork(); switch (pid){case -1:perror ("fork");break;case 0: // 子進(jìn)程printf ("我是子進(jìn)程,我的Id 是%d\n", getpid());sleep(1);exit(0);default: // 父進(jìn)程printf ("我是父進(jìn)程,Id = %d\n", getpid());break;}}while (1);return 0; }信號(hào)量
一、什么是信號(hào)量
為了防止出現(xiàn)因多個(gè)程序同時(shí)訪問一個(gè)共享資源而引發(fā)的一系列問題,我們需要一種方法,它可以通過生成并使用令牌來授權(quán),在任一時(shí)刻只能有一個(gè)執(zhí)行線程訪問代碼的臨界區(qū)域。臨界區(qū)域是指執(zhí)行數(shù)據(jù)更新的代碼需要獨(dú)占式地執(zhí)行。而信號(hào)量就可以提供這樣的一種訪問機(jī)制,讓一個(gè)臨界區(qū)同一時(shí)間只有一個(gè)線程在訪問它,也就是說信號(hào)量是用來調(diào)協(xié)進(jìn)程對(duì)共享資源的訪問的。
信號(hào)量是一個(gè)特殊的變量,程序?qū)ζ湓L問都是原子操作,且只允許對(duì)它進(jìn)行等待(即P(信號(hào)變量))和發(fā)送(即V(信號(hào)變量))信息操作。最簡(jiǎn)單的信號(hào)量是只能取0和1的變量,這也是信號(hào)量最常見的一種形式,叫做二進(jìn)制信號(hào)量。而可以取多個(gè)正整數(shù)的信號(hào)量被稱為通用信號(hào)量。這里主要討論二進(jìn)制信號(hào)量。
二、信號(hào)量的工作原理
由于信號(hào)量只能進(jìn)行兩種操作等待和發(fā)送信號(hào),即P(sv)和V(sv),他們的行為是這樣的:
P(sv):如果sv的值大于零,就給它減1;如果它的值為零,就掛起該進(jìn)程的執(zhí)行
V(sv):如果有其他進(jìn)程因等待sv而被掛起,就讓它恢復(fù)運(yùn)行,如果沒有進(jìn)程因等待sv而掛起,就給它加1.
舉個(gè)例子,就是兩個(gè)進(jìn)程共享信號(hào)量sv,一旦其中一個(gè)進(jìn)程執(zhí)行了P(sv)操作,它將得到信號(hào)量,并可以進(jìn)入臨界區(qū),使sv減1。而第二個(gè)進(jìn)程將被阻止進(jìn)入臨界區(qū),因?yàn)楫?dāng)它試圖執(zhí)行P(sv)時(shí),sv為0,它會(huì)被掛起以等待第一個(gè)進(jìn)程離開臨界區(qū)域并執(zhí)行V(sv)釋放信號(hào)量,這時(shí)第二個(gè)進(jìn)程就可以恢復(fù)執(zhí)行。
三、Linux的信號(hào)量機(jī)制
Linux提供了一組精心設(shè)計(jì)的信號(hào)量接口來對(duì)信號(hào)進(jìn)行操作,它們不只是針對(duì)二進(jìn)制信號(hào)量,下面將會(huì)對(duì)這些函數(shù)進(jìn)行介紹,但請(qǐng)注意,這些函數(shù)都是用來對(duì)成組的信號(hào)量值進(jìn)行操作的。它們聲明在頭文件sys/sem.h中。
1、semget函數(shù)
它的作用是創(chuàng)建一個(gè)新信號(hào)量或取得一個(gè)已有信號(hào)量,原型為:
第一個(gè)參數(shù)key是整數(shù)值(唯一非零),不相關(guān)的進(jìn)程可以通過它訪問一個(gè)信號(hào)量,它代表程序可能要使用的某個(gè)資源,程序?qū)λ行盘?hào)量的訪問都是間接的,程序先通過調(diào)用semget函數(shù)并提供一個(gè)鍵,再由系統(tǒng)生成一個(gè)相應(yīng)的信號(hào)標(biāo)識(shí)符(semget函數(shù)的返回值),只有semget函數(shù)才直接使用信號(hào)量鍵,所有其他的信號(hào)量函數(shù)使用由semget函數(shù)返回的信號(hào)量標(biāo)識(shí)符。如果多個(gè)程序使用相同的key值,key將負(fù)責(zé)協(xié)調(diào)工作。
第二個(gè)參數(shù)num_sems指定需要的信號(hào)量數(shù)目,它的值幾乎總是1。
第三個(gè)參數(shù)sem_flags是一組標(biāo)志,當(dāng)想要當(dāng)信號(hào)量不存在時(shí)創(chuàng)建一個(gè)新的信號(hào)量,可以和值IPC_CREAT做按位或操作。設(shè)置了IPC_CREAT標(biāo)志后,即使給出的鍵是一個(gè)已有信號(hào)量的鍵,也不會(huì)產(chǎn)生錯(cuò)誤。而IPC_CREAT | IPC_EXCL則可以創(chuàng)建一個(gè)新的,唯一的信號(hào)量,如果信號(hào)量已存在,返回一個(gè)錯(cuò)誤。
semget函數(shù)成功返回一個(gè)相應(yīng)信號(hào)標(biāo)識(shí)符(非零),失敗返回-1.
2、semop函數(shù)
它的作用是改變信號(hào)量的值,原型為:
sem_id是由semget返回的信號(hào)量標(biāo)識(shí)符,sembuf結(jié)構(gòu)的定義如下:
struct sembuf{ short sem_num;//除非使用一組信號(hào)量,否則它為0 short sem_op;//信號(hào)量在一次操作中需要改變的數(shù)據(jù),通常是兩個(gè)數(shù),一個(gè)是-1,即P(等待)操作, //一個(gè)是+1,即V(發(fā)送信號(hào))操作。 short sem_flg;//通常為SEM_UNDO,使操作系統(tǒng)跟蹤信號(hào), //并在進(jìn)程沒有釋放該信號(hào)量而終止時(shí),操作系統(tǒng)釋放信號(hào)量 };3、semctl函數(shù)
該函數(shù)用來直接控制信號(hào)量信息,它的原型為:
如果有第四個(gè)參數(shù),它通常是一個(gè)union semum結(jié)構(gòu),定義如下:
union semun{ int val; struct semid_ds *buf; unsigned short *arry; };前兩個(gè)參數(shù)與前面一個(gè)函數(shù)中的一樣,command通常是下面兩個(gè)值中的其中一個(gè)
SETVAL:用來把信號(hào)量初始化為一個(gè)已知的值。p 這個(gè)值通過union semun中的val成員設(shè)置,其作用是在信號(hào)量第一次使用前對(duì)它進(jìn)行設(shè)置。
IPC_RMID:用于刪除一個(gè)已經(jīng)無(wú)需繼續(xù)使用的信號(hào)量標(biāo)識(shí)符。
總結(jié)
以上是生活随笔為你收集整理的进程间通信之信号he信号量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 扎实的基础是成功的法宝
- 下一篇: Luogu P3731 [HAOI201