日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

进程间通信之信号he信号量

發(fā)布時(shí)間:2023/12/19 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 进程间通信之信号he信号量 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

信號(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:

#include <stdio.h> #include <signal.h>// 信號(hào)處理函數(shù) void handle(int signum) {printf ("捕捉到一個(gè)信號(hào) %d\n", signum); }int main() {signal(SIGINT, handle);signal(SIGTERM, handle);while (1);return 0; }

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)量,原型為:

int semget(key_t key, int num_sems, int sem_flags);

第一個(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)量的值,原型為:

int semop(int sem_id, struct sembuf *sem_opa, size_t num_sem_ops);

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)量信息,它的原型為:

int semctl(int sem_id, int sem_num, int command, ...);

如果有第四個(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í)符。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的进程间通信之信号he信号量的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。