❶ linux信號量
信號量是包含一個非負整數型的變數,並且帶有兩個原子操作wait和signal。Wait還可以被稱為down、P或lock,signal還可以被稱為up、V、unlock或post。在UNIX的API中(POSIX標准)用的是wait和post。
對於wait操作,如果信號量的非負整形變數S大於0,wait就將其減1,如果S等於0,wait就將調用線程阻塞;對於post操作,如果有線程在信號量上阻塞(此時S等於0),post就會解除對某個等待線程的阻塞,使其從wait中返回,如果沒有線程阻塞在信號量上,post就將S加1.
由此可見,S可以被理解為一種資源的數量,信號量即是通過控制這種資源的分配來實現互斥和同步的。如果把S設為1,那麼信號量即可使多線程並發運行。另外,信號量不僅允許使用者申請和釋放資源,而且還允許使用者創造資源,這就賦予了信號量實現同步的功能。可見信號量的功能要比互斥量豐富許多。
POSIX信號量是一個sem_t類型的變數,但POSIX有兩種信號量的實現機制: 無名信號量 和 命名信號量 。無名信號量只可以在共享內存的情況下,比如實現進程中各個線程之間的互斥和同步,因此無名信號量也被稱作基於內存的信號量;命名信號量通常用於不共享內存的情況下,比如進程間通信。
同時,在創建信號量時,根據信號量取值的不同,POSIX信號量還可以分為:
下面是POSIX信號量函數介面:
信號量的函數都以sem_開頭,線程中使用的基本信號函數有4個,他們都聲明在頭文件semaphore.h中,該頭文件定義了用於信號量操作的sem_t類型:
【sem_init函數】:
該函數用於創建信號量,原型如下:
該函數初始化由sem指向的信號對象,設置它的共享選項,並給它一個初始的整數值。pshared控制信號量的類型,如果其值為0,就表示信號量是當前進程的局部信號量,否則信號量就可以在多個進程間共享,value為sem的初始值。
該函數調用成功返回0,失敗返回-1。
【sem_destroy函數】:
該函數用於對用完的信號量進行清理,其原型如下:
成功返回0,失敗返回-1。
【sem_wait函數】:
該函數用於以原子操作的方式將信號量的值減1。原子操作就是,如果兩個線程企圖同時給一個信號量加1或減1,它們之間不會互相干擾。其原型如下:
sem指向的對象是sem_init調用初始化的信號量。調用成功返回0,失敗返回-1。
sem_trywait()則是sem_wait()的非阻塞版本,當條件不滿足時(信號量為0時),該函數直接返回EAGAIN錯誤而不會阻塞等待。
sem_timedwait()功能與sem_wait()類似,只是在指定的abs_timeout時間內等待,超過時間則直接返回ETIMEDOUT錯誤。
【sem_post函數】:
該函數用於以原子操作的方式將信號量的值加1,其原型如下:
與sem_wait一樣,sem指向的對象是由sem_init調用初始化的信號量。調用成功時返回0,失敗返回-1。
【sem_getvalue函數】:
該函數返回當前信號量的值,通過restrict輸出參數返回。如果當前信號量已經上鎖(即同步對象不可用),那麼返回值為0,或為負數,其絕對值就是等待該信號量解鎖的線程數。
【實例1】:
【實例2】:
之所以稱為命名信號量,是因為它有一個名字、一個用戶ID、一個組ID和許可權。這些是提供給不共享內存的那些進程使用命名信號量的介面。命名信號量的名字是一個遵守路徑名構造規則的字元串。
【sem_open函數】:
該函數用於創建或打開一個命名信號量,其原型如下:
參數name是一個標識信號量的字元串。參數oflag用來確定是創建信號量還是連接已有的信號量。
oflag的參數可以為0,O_CREAT或O_EXCL:如果為0,表示打開一個已存在的信號量;如果為O_CREAT,表示如果信號量不存在就創建一個信號量,如果存在則打開被返回,此時mode和value都需要指定;如果為O_CREAT|O_EXCL,表示如果信號量存在則返回錯誤。
mode參數用於創建信號量時指定信號量的許可權位,和open函數一樣,包括:S_IRUSR、S_IWUSR、S_IRGRP、S_IWGRP、S_IROTH、S_IWOTH。
value表示創建信號量時,信號量的初始值。
【sem_close函數】:
該函數用於關閉命名信號量:
單個程序可以用sem_close函數關閉命名信號量,但是這樣做並不能將信號量從系統中刪除,因為命名信號量在單個程序執行之外是具有持久性的。當進程調用_exit、exit、exec或從main返回時,進程打開的命名信號量同樣會被關閉。
【sem_unlink函數】:
sem_unlink函數用於在所有進程關閉了命名信號量之後,將信號量從系統中刪除:
【信號量操作函數】:
與無名信號量一樣,操作信號量的函數如下:
命名信號量是隨內核持續的。當命名信號量創建後,即使當前沒有進程打開某個信號量,它的值依然保持,直到內核重新自舉或調用sem_unlink()刪除該信號量。
無名信號量的持續性要根據信號量在內存中的位置確定:
很多時候信號量、互斥量和條件變數都可以在某種應用中使用,那這三者的差異有哪些呢?下面列出了這三者之間的差異:
❷ linux文件鎖定被使用
一、什麼是文件鎖定
對於鎖這個字,大家一定不會陌生,因為我們生活中就存在著大量的鎖,它們各個方面發揮著它的作用,現在世界中的鎖的功能都可歸結為一句話,就是阻止某些人做某些事,例如,門鎖就是阻止除了屋主之外的人進入這個房子,你進入不到這個房子,也就不能使用房子裡面的東西。
而因為程序經常需要共享數據,而這通常又是通過文件來實現的,試想一個情況,A進程正在對一個文件進行寫操作,而另一個程序B需要對同一個文件進行讀操作,並以讀取到的數據作為自己程序運行時所需要的數據,這會發生什麼情況呢?進程B可能會讀到錯亂的數據,因為它並不知道另一個進程A正在改寫這個文件中的數據。
為了解決類似的問題,就出現了文件鎖定,簡單點來說,這是文件的一種安全的更新方式,當一個程序正在對文件進行寫操作時,文件就會進入一種暫時狀態,在這個狀態下,如果另一個程序嘗試讀這個文件,它就會自動停下來等待這個狀態結束。Linux系統提供了很多特性來實現文件鎖定,其中最簡單的方法就是以原子操作的方式創建鎖文件。
用回之前的例子就是,文件鎖就是當文件在寫的時候,阻止其他的需要寫或者要讀文件的進程來操作這個文件。
二、創建鎖文件
創建一個鎖文件是非常簡單的,我們可以使用open系統調用來創建一個鎖文件,在調用open時oflags參數要增加參數O_CREAT和O_EXCL標志,如file_desc = open("/tmp/LCK.test", O_RDWR|O_CREAT|O_EXCL, 0444);就可以創建一個鎖文件/tmp/LCK.test。O_CREAT|O_EXCL,可以確保調用者可以創建出文件,使用這個模式可以防止兩個程序同時創建同一個文件,如果文件(/tmp/LCK.test)已經存在,則open調用就會失敗,返回-1。
如果一個程序在它執行時,只需要獨占某個資源一段很短的時間,這個時間段(或代碼區)通常被叫做臨界區,我們需要在進入臨界區之前使用open系統調用創建鎖文件,然後在退出臨界區時用unlink系統調用刪除這個鎖文件。
注意:鎖文件只是充當一個指示器的角色,程序間需要通過相互協作來使用它們,也就是說鎖文件只是建議鎖,而不是強制鎖,並不會真正阻止你讀寫文件中的數據。
可以看看下面的例子:源文件文件名為filelock1.c,代碼如下:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> int main() { const char *lock_file = "/tmp/LCK.test1"; int n_fd = -1; int n_tries = 10; while(n_tries--) { //創建鎖文件 n_fd = open(lock_file, O_RDWR|O_CREAT|O_EXCL, 0444); if(n_fd == -1) { //創建失敗 printf("%d - Lock already present ", getpid()); sleep(2); } else { //創建成功 printf("%d - I have exclusive access ", getpid()); sleep(1); close(n_fd); //刪除鎖文件,釋放鎖 unlink(lock_file); sleep(2); } } return 0; }
同時運行同一個程序的兩個實例,運行結果為:
從運行的結果可以看出兩個程序交叉地對對文件進行鎖定,但是真實的操作卻是,每次調用open函數去檢查/tmp/LCK.test1這個文件是否存在,如果存在open調用就失敗,顯示有進程已經把這個文件鎖定了,如果這個文件不存在,就創建這個文件,並顯示許可信息。但是這種做法有一定的缺憾,我們可以看到文件/tmp/LCK.test1被創建了很多次,也被unlink刪除了很多次,也就是說我們不能使用已經事先有數據的文件作為這種鎖文件,因為如果文件已經存在,則open調用總是失敗。
給我的感覺是,這更像是一種對進程工作的協調性安排,更像是二進制信號量的作用,文件存在為0,不存在為1,而不是真正的文件鎖定。
三、區域鎖定
我們還有一個問題,就是如果同一個文件有多個進程需要對它進行讀寫,而一個文件同一時間只能被一個進程進行寫操作,但是多個進程讀寫的區域互不相關,如果總是要等一個進程寫完其他的進程才能對其進行讀寫,效率又太低,那麼是否可以讓多個進程同時對文件進行讀寫以提高數據讀寫的效率呢?
為了解決上面提到的問題,和出現在第二點中的問題,即不能把文件鎖定到指定的已存在的數據文件上的問題,我們提出了一種新的解決方案,就是區域鎖定。
簡單點來說,區域鎖定就是,文件中的某個部分被鎖定了,但其他程序可以訪問這個文件中的其他部分。
然而,區域鎖定的創建和使用都比上面說的文件鎖定復雜很多。
1、創建區域鎖定
在Linux上為實現這一功能,我們可以使用fcntl系統調用和lockf調用,但是下面以fcntl系統調用來講解區域鎖定的創建。
fctnl的函數原理為:
int fctnl(int fildes, int command, ...);
它對一個打開的文件描述進行操作,並能根據command參數的設置完成不同的任務,它有三個可選的任務:F_GETLK,F_SETLK,F_SETLKW,至於這三個參數的意義下面再詳述。而當使用這些命令時,fcntl的第三個參數必須是一個指向flock結構的指針,所以在實際應用中,fctnl的函數原型一般為:int fctnl(int fildes, int command, struct flock *flock_st);
2、flock結構
准確來說,flock結構依賴具體的實現,但是它至少包括下面的成員:
short l_type;文件鎖的類型,對應於F_RDLCK(讀鎖,也叫共享鎖),F_UNLCK(解鎖,也叫清除鎖),F_WRLCK(寫鎖,也叫獨占鎖)中的一個。
short l_whence;從文件的哪個相對位置開始計算,對應於SEEK_SET(文件頭),SEEK_CUR(當前位置),SEEK_END(文件尾)中的一個。
off_t l_start;從l_whence開始的第l_start個位元組開始計算。
off_t l_len;鎖定的區域的長度。
pid_t l_pid;用來記錄參持有鎖的進程。
成員l_whence、l_start和l_len定義了一個文件中的一個區域,即一個連續的位元組集合,例如:
struct flock region;
region.l_whence = SEEK_SET;
region.l_start = 10;
region.l_len = 20;
則表示fcntl函數操作鎖定的區域為文件頭開始的第10到29個位元組之間的這20個位元組。
3、文件鎖的類型
從上面的flock的成員l_type的取值我們可以知道,文件鎖的類型主要有三種,這里對他們進行詳細的解說。
F_RDLCK:
從它的名字我們就可以知道,它是一個讀鎖,也叫共享鎖。許多不同的進程可以擁有文件同一(或重疊)區域上的讀(共享)鎖。而且只要任一進程擁有一把讀(共享)鎖,那麼就沒有進程可以再獲得該區域上的寫(獨占)鎖。為了獲得一把共享鎖,文件必須以「讀」或「讀/寫」方式打開。
簡單點來說就是,當一個進程在讀文件中的數據時,文件中的數據不能被改變或改寫,這是為了防止數據被改變而使讀數據的程序讀取到錯亂的數據,而文件中的同一個區域能被多個進程同時讀取,這是容易理解的,因為讀不會破壞數據,或者說讀操作不會改變文件的數據。
F_WRLCK:
從它的名字,我們就可以知道,它是一個寫鎖,也叫獨占鎖。只有一個進程可以在文件中的任一特定區域擁有一把寫(獨占)鎖。一旦一個進程擁有了這樣一把鎖,任何其他進程都無法在該區域上獲得任何類型的鎖。為了獲得一把寫(獨占)鎖,文件也必須以「讀」或「讀/寫」方式打開。
簡單點來說,就是一個文件同一區域(或重疊)區域進在同一時間,只能有一個進程能對其進行寫操作,並且在寫操作進行期間,其他的進程不能對該區域進行讀取數據。這個要求是顯然易見的,因為如果兩個進程同時對一個文件進行寫操作,就會使文件的內容錯亂起來,而由於寫時會改變文件中的數據,所以它也不允許其他進程對文件的數據進行讀取和刪除文件等操作。
F_UNLCK:
從它的名字就可以知道,它用於把一個鎖定的區域解鎖。
4、不同的command的意義
在前面說到fcntl函數的command參數時,說了三個命令選項,這里將對它們進行詳細的解說。
F_GETLK命令,它用於獲取fildes(fcntl的第一個參數)打開的文件的鎖信息,它不會嘗試去鎖定文件,調用進程可以把自己想創建的鎖類型信息傳遞給fcntl,函數調用就會返回將會阻止獲取鎖的任何信息,即它可以測試你想創建的鎖是否能成功被創建。fcntl調用成功時,返回非-1,如果鎖請求可以成功執行,flock結構將保持不變,如果鎖請求被阻止,fcntl會用相關的信息覆蓋flock結構。失敗時返回-1。
所以,如果調用成功,調用程序則可以通過檢查flock結構的內容來判斷其是否被修改過,來檢查鎖請求能否被成功執行,而又因為l_pid的值會被設置成擁有鎖的進程的標識符,所以大多數情況下,可以通過檢查這個欄位是否發生變化來判斷flock結構是否被修改過。
使用F_GETLK的fcntl函數調用後會立即返回。
舉個例子來說,例如,有一個flock結構的變數,flock_st,flock_st.l_pid = -1,文件的第10~29個位元組已經存在一個讀鎖,文件的第40~49個位元組中已經存在一個寫鎖,則調用fcntl時,如果用F_GETLK命令,來測試在第10~29個位元組中是否可以創建一個讀鎖,因為這個鎖可以被創建,所以,fcntl返回非-1,同時,flock結構的內容也不會改變,flock_st.l_pid = -1。而如果我們測試第40~49個位元組中是否可以創建一個寫鎖時,由於這個區域已經存在一個寫鎖,測試失敗,但是fcntl還是會返回非-1,只是flock結構會被這個區域相關的鎖的信息覆蓋了,flock_st.l_pid為擁有這個寫鎖的進程的進程標識符。
F_SETLK命令,這個命令試圖對fildes指向的文件的某個區域加鎖或解鎖,它的功能根據flock結構的l_type的值而定。而對於這個命令來說,flock結構的l_pid欄位是沒有意義的。如果加鎖成功,返回非-1,如果失敗,則返回-1。使用F_SETLK的fcntl函數調用後會立即返回。
F_SETLKW命令,這個命令與前面的F_SETLK,命令作用相同,但不同的是,它在無法獲取鎖時,即測試不能加鎖時,會一直等待直到可以被加鎖為止。
5、例子
看了這么多的說明,可能你已經很亂了,就用下面的例子來整清你的思想吧。
源文件名為filelock2.c,用於創建數據文件,並將文件區域加鎖,代碼如下:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> int main() { const char *test_file = "test_lock.txt"; int file_desc = -1; int byte_count = 0; char *byte_to_write = "A"; struct flock region_1; struct flock region_2; int res = 0; //打開一個文件描述符 file_desc = open(test_file, O_RDWR|O_CREAT, 0666); if(!file_desc) { fprintf(stderr, "Unable to open %s for read/write ", test_file); exit(EXIT_FAILURE); } //給文件添加100個『A』字元的數據 for(byte_count = 0; byte_count < 100; ++byte_count) { write(file_desc, byte_to_write, 1); } //在文件的第10~29位元組設置讀鎖(共享鎖) region_1.l_type = F_RDLCK; region_1.l_whence = SEEK_SET; region_1.l_start = 10; region_1.l_len = 20; //在文件的40~49位元組設置寫鎖(獨占鎖) region_2.l_type = F_WRLCK; region_2.l_whence = SEEK_SET; region_2.l_start = 40; region_2.l_len = 10; printf("Process %d locking file ", getpid()); //鎖定文件 res = fcntl(file_desc, F_SETLK, ®ion_1); if(res == -1) { fprintf(stderr, "Failed to lock region 1 "); } res = fcntl(file_desc, F_SETLK, ®ion_2); if(res == -1) { fprintf(stderr, "Failed to lock region 2 "); } //讓程序休眠一分鍾,用於測試 sleep(60); printf("Process %d closing file ", getpid()); close(file_desc); exit(EXIT_SUCCESS); }
下面的源文件filelock3.c用於測試上一個文件設置的鎖,測試可否對兩個區域都加上一個讀鎖,代碼如下:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> int main() { const char *test_file = "test_lock.txt"; int file_desc = -1; int byte_count = 0; char *byte_to_write = "A"; struct flock region_1; struct flock region_2; int res = 0; //打開數據文件 file_desc = open(test_file, O_RDWR|O_CREAT, 0666); if(!file_desc) { fprintf(stderr, "Unable to open %s for read/write ", test_file); exit(EXIT_FAILURE); } //設置區域1的鎖類型 struct flock region_test1; region_test1.l_type = F_RDLCK; region_test1.l_whence = SEEK_SET; region_test1.l_start = 10; region_test1.l_len = 20; region_test1.l_pid = -1; //設置區域2的鎖類型 struct flock region_test2; region_test2.l_type = F_RDLCK; region_test2.l_whence = SEEK_SET; region_test2.l_start = 40; region_test2.l_len = 10; region_test2.l_pid = -1; //
三、解空鎖問題
如果我要給在本進程中沒有加鎖的區域解鎖會發生什麼事情呢?而如果這個區域中其他的進程有對其進行加鎖又會發生什麼情況呢?
如果一個進程實際並未對一個區域進行鎖定,而調用解鎖操作也會成功,但是它並不能解其他的進程加在同一區域上的鎖。也可以說解鎖請求最終的結果取決於這個進程在文件中設置的任何鎖,沒有加鎖,但對其進行解鎖得到的還是沒有加鎖的狀態。
❸ Linux信號 機制和Linux信號量機制的區別
首先,一句話總結它們之間的區別:
字面上相似,但是本質上存在巨大的差別!請看詳細解答...
Linux信號(signal) 機制
signal,又簡稱為信號(軟中斷信號)用來通知進程發生了非同步事件。
原理:
一個進程收到一個信號與處理器收到一個中斷請求可以說是一樣的。信號是進程間通信機制中唯一的非同步通信機制,一個進程不必通過任何操作來等待信號的到達,事實上,進程也不知道信號到底什麼時候到達。進程之間可以互相通過系統調用kill發送軟中斷信號。內核也可以因為內部事件而給進程發送信號,通知進程發生了某個事件。信號機制除了基本通知功能外,還可以傳遞附加信息。
分類:
從兩個不同的分類角度對信號進行:
可靠性方面:可靠信號與不可靠信號;
與時間的關繫上:實時信號與非實時信號。
部分定義轉自:http://www.cnblogs.com/hoys/archive/2012/08/19/2646377.html
Linux信號量(semaphore)機制
Linux內核的信號量用來操作系統進程間同步訪問共享資源。
原理:信號量在創建時需要設置一個初始值,表示同時可以有幾個任務可以訪問該信號量保護的共享資源,初始值為1就變成互斥鎖(Mutex),即同時只能有一個任務可以訪問信號量保護的共享資源。
一個任務要想訪問共享資源,首先必須得到信號量,獲取信號量的操作將把信號量的值減1,若當前信號量的值為負數,表明無法獲得信號量,該任務必須掛起在該信號量的等待隊列等待該信號量可用;若當前信號量的值為非負數,表示可以獲得信號量,因而可以立刻訪問被該信號量保護的共享資源。
當任務訪問完被信號量保護的共享資源後,必須釋放信號量,釋放信號量通過把信號量的值加1實現,如果信號量的值為非正數,表明有任務等待當前信號量,因此它也喚醒所有等待該信號量的任務。
常用的信號量的API:
DECLARE_MUTEX(name)
該宏聲明一個信號量name並初始化它的值為0,即聲明一個互斥鎖。
DECLARE_MUTEX_LOCKED(name)
該宏聲明一個互斥鎖name,但把它的初始值設置為0,即鎖在創建時就處在已鎖狀態。因此對於這種鎖,一般是先釋放後獲得。
void sema_init (struct semaphore *sem, int val);
該函用於數初始化設置信號量的初值,它設置信號量sem的值為val。
void init_MUTEX (struct semaphore *sem);
該函數用於初始化一個互斥鎖,即它把信號量sem的值設置為1。
void init_MUTEX_LOCKED (struct semaphore *sem);
該函數也用於初始化一個互斥鎖,但它把信號量sem的值設置為0,即一開始就處在已鎖狀態。
void down(struct semaphore * sem);
該函數用於獲得信號量sem,它會導致睡眠,因此不能在中斷上下文(包括IRQ上下文和softirq上下文)使用該函數。該函數將把sem的值減1,如果信號量sem的值非負,就直接返回,否則調用者將被掛起,直到別的任務釋放該信號量才能繼續運行。
int down_interruptible(struct semaphore * sem);
該函數功能與down類似,不同之處為,down不會被信號(signal)打斷,但down_interruptible能被信號打斷,因此該函數有返回值來區分是正常返回還是被信號中斷,如果返回0,表示獲得信號量正常返回,如果被信號打斷,返回-EINTR。
int down_trylock(struct semaphore * sem);
該函數試著獲得信號量sem,如果能夠立刻獲得,它就獲得該信號量並返回0,否則,表示不能獲得信號量sem,返回值為非0值。因此,它不會導致調用者睡眠,可以在中斷上下文使用。
void up(struct semaphore * sem);
該函數釋放信號量sem,即把sem的值加1,如果sem的值為非正數,表明有任務等待該信號量,因此喚醒這些等待者。
實例:
信號量在絕大部分情況下作為互斥鎖使用,下面以console驅動系統為例說明信號量的使用。
在內核源碼樹的kernel/printk.c中,使用宏DECLARE_MUTEX聲明了一個互斥鎖console_sem,它用於保護console驅動列表console_drivers以及同步對整個console驅動系統的訪問。
❹ linux 怎麼查 信號量 被進程p住
這篇文章將講述別一種進程間通信的機制——信號量。注意請不要把它與之前所說的信號混淆起來,信號與信號量是不同的兩種事物。有關信號的更多內容,可以閱讀我的另一篇文章:Linux進程間通信——使用信號。下面就進入信號量的講解。
一、什麼是信號量
為了防止出現因多個程序同時訪問一個共享資源而引發的一系列問題,我們需要一種方法,它可以通過生成並使用令牌來授權,在任一時刻只能有一個執行線程訪問代碼的臨界區域。臨界區域是指執行數據更新的代碼需要獨占式地執行。而信號量就可以提供這樣的一種訪問機制,讓一個臨界區同一時間只有一個線程在訪問它,也就是說信號量是用來調協進程對共享資源的訪問的。
信號量是一個特殊的變數,程序對其訪問都是原子操作,且只允許對它進行等待(即P(信號變數))和發送(即V(信號變數))信息操作。最簡單的信號量是只能取0和1的變數,這也是信號量最常見的一種形式,叫做二進制信號量。而可以取多個正整數的信號量被稱為通用信號量。這里主要討論二進制信號量。
二、信號量的工作原理
由於信號量只能進行兩種操作等待和發送信號,即P(sv)和V(sv),他們的行為是這樣的:
P(sv):如果sv的值大於零,就給它減1;如果它的值為零,就掛起該進程的執行
V(sv):如果有其他進程因等待sv而被掛起,就讓它恢復運行,如果沒有進程因等待sv而掛起,就給它加1.
舉個例子,就是兩個進程共享信號量sv,一旦其中一個進程執行了P(sv)操作,它將得到信號量,並可以進入臨界區,使sv減1。而第二個進程將被阻止進入臨界區,因為當它試圖執行P(sv)時,sv為0,它會被掛起以等待第一個進程離開臨界區域並執行V(sv)釋放信號量,這時第二個進程就可以恢復執行。
三、Linux的信號量機制
Linux提供了一組精心設計的信號量介面來對信號進行操作,它們不只是針對二進制信號量,下面將會對這些函數進行介紹,但請注意,這些函數都是用來對成組的信號量值進行操作的。它們聲明在頭文件sys/sem.h中。
❺ linux 信號量是什麼怎麼用
Linux信號量(semaphore)是一種互斥機制。即對某個互斥資源的訪問會收到信號量的保護,在訪問之前需要獲得信號量。
在操作完共享資源後,需釋放信號量,以便另外的進程來獲得資源。獲得和釋放應該成對出現。
獲得信號量集,需要注意的是,獲得的是一個集合,而不是一個單一的信號量。
#include
#include
#include
1: int semget(key_t key,int nsems,int semflg);
key:系統根據這個值來獲取信號量集。
nsems:此信號集包括幾個信號量。
semflg:創建此信號量的屬性。 (IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR)
成功則返回該信號量集的ID。
註:
既指定IPC_CREAT又指定IPC_EXCL時,如果系統中該信號量集已經存在,則馬上返回。
如果需要獲得存在的信號量,則將此參數置0.
2: int semctl(int semid,int senum,int cmd....)
semid:信號量ID。
senum:對信號量集中的第幾個信號量進行控制。(從0開始)
cmd:需要進行的操作。(SETVAL是其中的一個)。
根據cmd的不同可能存在第四個參數,cmd=SETVAL時,表示同時信號量可以被獲得幾次,如第四個參數
num=1表示只能被獲得一次,既被信號量保護的資源只能同時被一個程序使用。
該系統調用,是在對信號量初始化時用的。
-3: 「3」前面加了"-"表示當需要使用互斥資源時應該做這步。
int semop(int semid,struct sembuf *sem,int num_elements);
struct sembuf {
unsigned short sem_num; //該信號量集中的第幾個信號量。
int sem_op;//需要獲得還是釋放信號量
int sem_flg;//相關動作
};
num_elements:需要對該信號量集中的多少個信號量進行處理。
獲得信號量時,將sembuf結構提初始化為:
sem_num = 0; //該信號量集中的首個信號量
sem_op = -1; //獲得信號量
sem_flag = IPC_NOWAIT; //如果不能獲得信號量,馬上返回。
semop(semid,_sem,1);
同理釋放信號量時,將sem_op設為1.
以上是對信號量的簡單處理
❻ linux 信號量是什麼怎麼用
信號量與互斥鎖之間的區別:1. 互斥量用於線程的互斥,信號量用於線程的同步。 這是互斥量和信號量的根本區別,也就是互斥和同步之間的區別。 互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。 同步:是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源 2. 互斥量值只能為0/1,信號量值可以為非負整數。 也就是說,一個互斥量只能用於一個資源的互斥訪問,它不能實現多個資源的多線程互斥問題。信號量可以實現多個同類資源的多線程互斥和同步。當信號量為單值信號量是,也可以完成一個資源的互斥訪問。 3. 互斥量的加鎖和解鎖必須由同一線程分別對應使用,信號量可以由一個線程釋放,另一個線程得到。
❼ linux常用信號量
linux的常用信號量
BUS與SEGV
二者都是錯誤信號,BUS表示匯流排錯誤,SEGV表示段錯誤,程序崩潰的時候99%都是這兩個錯誤導
致的。進程可以捕獲和封鎖這兩類錯誤。內核對二者的默認處理是memory mp
WINCH
窗口改變信號(WINdown CHanged)。例如虛擬終端的行數發生變化時將發送WINCH信號,絕大多數
文本編輯器都能捕獲WINCH信號自動進行重新配置。內核的默認處理是忽略該信號,並且不進行內存
轉儲。
進程可以捕獲或者封鎖該信號
KILL
殺死/刪除進程,編號為9
STOP
掛起/暫停正在執行的進程,直到收到CONT為止
KILL STOP都不能夠被捕獲、封鎖或者忽略,默認處理都不會產生內存轉儲。
CONT
取消掛起,繼續執行進程
TSTP
是STOP信號的「軟」版本,即在用戶輸入Ctrl+Z時由終端驅動程序發送的信號。捕獲到該信號的進程通常
清除它們的狀態,如何給自己發送一個STOP信號。TSTP的默認處理不會導致內存轉儲。
INT
中斷信號,編號為2
當用戶輸入Ctrl+C時由終端驅動程序發送INT信號
INT信號是終止當前操作的請求,簡單程序捕獲到INT信號時應該退出,擁有命令行或者輸入模式的那些
程序應該停止他們正在做的事情,清除狀態,並等待用戶再次輸入。
TERM
軟體終止信號,編號為15
TERM是請求徹底終止某項操作的信號,它期望進程清楚自己的狀態並退出
QUIT
退出信號,編號為3
與TERM類似,不同之處在於QUIT信號的默認處理是內存轉儲,而TERM信號的默認處理沒有內存轉儲。
HUP
掛起信號,編號為1,有兩種解釋:
守護進程理解HUP為重新設置的請求,如果守護進程能夠不用重新啟動就能夠重新讀取它自己的配置文
件並調整自己以適應變化的話,那麼HUP信號通常可以用來觸發這種行為
HUP
信號有時有終端驅動程序生成,試圖用來清除(也就是終止)跟某個特定終端相連接的那些進程。例如
當一個終端會話結束時,或者當一個Modem的連接不經意的斷開時,就可能出現這種情況。
如果需要某些進程在會話結束之後繼續運行,那麼在C Shell中設法讓這些進程變成後台程序,
ksh或者bash中可以用nohup來模擬這種行為。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
進程的四種狀態
runnable(可運行狀態)
只要有CPU時間,進程就可以執行。一旦進程執行了不能立即完成的系統調用,Linux會把進程轉入
睡眠狀態
sleeping(睡眠狀態)
進程在等待某些事件發生(如終端輸入、網路連接)
zombie(僵化狀態)
進程已經執行完畢並試圖消亡,但是狀態沒有收集完
stopped(停止狀態)
進程被掛起,不允許執行。進程收到STOP或者TSTP信號即進入停止狀態,可以用CONT信號來重新啟動