Linux 程序間通訊(四)訊號量

2021-08-28 09:38:19 字數 4052 閱讀 8795

訊號量和其他ipc不同,並沒有在程序之間傳送資料,訊號量用於多程序在訪問共享資源時的同步控制就像交通路口的紅路燈一樣,當訊號量大於0,表示綠燈允許通過,當訊號量等於0,表示紅燈,必須停下來等待綠燈才能通過。

程序間的互斥關係與同步關係存在的根源在於臨界資源。

臨界資源是在同乙個時刻只允許有限個(通常只有乙個) 程序可以訪問(讀) 或修改(寫)的資源, 通常包括硬體資源(處理器、 記憶體、 儲存器及其他外圍裝置等) 和軟體資源(共享**段、 共享結構和變數等)。訪問臨界資源的**叫做臨界區, 臨界區本身也會成為臨界資源。

訊號量是用來解決程序間的同步與互斥問題的一種程序間通訊機制,包括乙個稱為訊號量的變數和在該訊號量下等待資源的程序等待列, 以及對訊號量進行的兩個原子操作(pv操作)。 其中訊號量對應於某一種資源, 取乙個非負的整型值。 訊號量值指的是當前可用的該資源的數量, 若等於 0 則意味著目前沒有可用的資源。pv 原子操作的具體定義如下。

常見的使用訊號量訪問臨界區的偽**如下

最簡單的訊號量只能取 0 和 1 兩種值, 這種訊號量叫做二維訊號量。 這裡主要討論二維訊號量。 二維訊號量的應用比較容易擴充套件到使用多維訊號量的情況。

2.1  函式說明

在 linux 系統中, 使用訊號量通常分為以下幾個步驟:

(1) 建立訊號量或獲得在系統中已存在的訊號量, 此時需要呼叫 semget()函式。 不同程序通過使用同乙個訊號量鍵值來獲得同乙個訊號量。

(2) 初始化訊號量, 此時使用 semctl()函式的 setval 操作。 當使用二維訊號量時, 通常將訊號量初始化為 1。

(3) 進行訊號量的 pv 操作, 此時呼叫 semop()函式。 這一步是實現程序間的同步和互斥的核心工作部分。

(4)如果不需要訊號量, 則從系統中刪除它, 此時使用 semctl ()函式的 ipc_rmid 操作。需要注意的是, 在程式中不應該出現對已經被刪除的訊號量的操作。

注意:建立了乙個訊號就會在系統中一直存在,直到我們去刪除

這裡列舉了 semget()函式的語法要點。

key:如果為ipc_private,則表示建立訊號量,如果key不為ipc_private且key所對應的訊號量已經存在,則返回訊號量

nsems:需要建立的訊號量數目, 通常取值為 1

sem***:

如果semget用於建立新的訊號量,則的值為ipc_creat  |  perm,perm為新建立訊號量的訪問許可權

如果semget用於獲得已經存在的訊號量則sem***的值為0

例項**:

#include #include #include #include #include #include #include #include int main(void)

else

return 0;

}

# ./a.out

新建訊號的識別符號,值為 [65538]

建立的識別符號的值,不等於在semget函式中給定的key值

int semop(int semid, struct sembuf *sops, size_t nsops)

semid: semget()函式返回的訊號量識別符號

sops:指向訊號量運算元組, 乙個陣列包括以下成員。

nsops:運算元組 sops 中的操作個數(元素數目) , 通常取值為 1(乙個操作)

struct sembuf
sem_op  >  0:那麼操作將sem_op加入到訊號量的值中,並喚醒等待訊號增加的程序

sem_op  ==  0:當訊號量的值是0時,函式返回,否則阻塞直到訊號量的值為0

sem_op  當前訊號量   +  sem_op   的值

如果為0,喚醒等待訊號量為0的程序,

如果小於0,呼叫該函式的程序阻塞,

如果大於0,那麼訊號量減去這個值並返回

#include #include #include #include #include #include #include #include #include #include int main(void)

printf("值為 [%d]\n", semid);

}return 0;

}

#include #include #include #include #include #include #include #include #include #include int main(void)

printf("值為 [%d]\n", semid);

}return 0;

}

結果:終端1執行獲取訊號量的**,如果它沒有獲取到訊號量,就會一直阻塞,直到終端2釋放訊號量

刪除訊號量例項**:

#include #include #include #include #include #include #include #include #include #include int main(void)

else

} return 0;

}

#include #include #include #include #include #include #include #include #include #include union semun ;

/* 訊號量初始化(賦值) 函式 */

int init_sem(int sem_id, int init_value)

return 0;

} /* 從系統中刪除訊號量的函式 */

int del_sem(int sem_id)

} /* p 操作函式 */

int sem_p(int sem_id)

return 0;

}/* v 操作函式 */

int sem_v(int sem_id)

return 0;

}int main(void)

else if (result == 0) /* 返回值為 0 代表子程序 */

else /* 返回值大於 0 代表父程序 */

exit(0);

}

結果:# ./a.out 

子程序一下

父程序一下

子程序再一下

父程序再一下

1.訊號量類似於執行緒中的互斥鎖,(乙個執行緒上鎖後,另乙個執行緒要等待另乙個程序解鎖後才能繼續執行)2.定義了乙個訊號量後,會一直在系統中存在3.訊號量比互斥鎖複雜太多了4.semctl函式中的union semun需要自己定義5.如果多個程序等待乙個訊號量,就把訊號量的值設定為大於1

linux 訊號量(程序間通訊)

將使用乙個程式來演示訊號量的使用,程式用pv操作控制訊號量,以操作臨界區,p操作讓訊號量減1,v操作讓訊號量加1,而pv操作之間的 即為臨界區關鍵 每次只能由乙個程序訪問。程式建立出乙個子程序,在兩個程序中分別有一段臨界區關鍵 實現的功能都是不斷的順序輸出0 9的字元。保證程序間同步 plain v...

linux 程序間通訊 訊號量

例項中首先使用fork 建立乙個子程序,在父程序呼叫kill 之前,在子程序中使用raise 向自身傳送sigstop訊號,是子程序暫停。接下來使用kill 向子程序傳送訊號 ngnsvr9 none home xionghailong example cat kill raise.c includ...

Linux 程序間通訊 訊號量

linux學習目錄 1 什麼是訊號量?在對於臨界區資源管理過程中,為了防止多個程式同時訪問乙個共享資源而引發的一系列問題。比如 死鎖。為了解決這種問題,巨人們就發明了訊號量。訊號量就是為了解決在乙個臨界區只有乙個程序訪問它,也就是說訊號量相當於交警,來協調程序對共享資源有序的訪問而不造成死鎖等行為。...