導航:首頁 > 操作系統 > 共享鎖linux

共享鎖linux

發布時間:2022-06-08 12:51:06

A. linux共享鎖與排斥鎖的作用

共享鎖【S鎖】又稱讀鎖,若事務T對數據對象A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這保證了其他事務可以讀A,但在T釋放A上的S鎖之前不能對A做任何修改。排他鎖【X鎖】又稱寫鎖。若事務T對數據對象A加上X鎖,事務T可以讀A也可以修改A,其他事務不能再對A加任何鎖,直到T釋放A上的鎖。這保證了其他事務在T釋放A上的鎖之前不能再讀取和修改A。

B. 操作系統,linux中 lockf(1,1,0);和 lockf(1,0,0); 是什麼作用

ockf(fd,1,0)是給fd文件上鎖,lockf(fd,0,0)是解鎖,配合使用,實現進程的互斥。

頭文件

#include <sys/file.h>

函數:

int lockf(int fd, int cmd, off_t len);

fd -- 文件id.

fcntl(2)的介面(inteface)函數

返回1表示調用lockf成功.

lockf用於鎖定或打開鎖定一個共享文件.

操作有:

F_LOCK(鎖定),F_TLOCK,F_ULOCK(打開鎖定),F_TEST

(2)共享鎖linux擴展閱讀:

注意事項

lockf()函數允許將文件區域用作信號量(監視鎖),或用於控制對鎖定進程的訪問(強制模式記錄鎖定)。試圖訪問已鎖定資源的其他進程將返回錯誤或進入休眠狀態,直到資源解除鎖定為止。當關閉文件時,將釋放進程的所有鎖定,即使進程仍然有打開的文件。當進程終止時,將釋放進程保留的所有鎖定。

函數聲明:

/* 'lockf' is a simpler interface to the locking facilities of 'fcntl'. LEN is always relative to the current file position. The CMD argument is one of the following. This function is a cancellation point and therefore not marked with __THROW. */

#include <unistd.h>

int lockf(int fd, int cmd, off_t len);

C. linux有沒有多進程間的讀寫鎖

Linux共享內存可以不用加鎖,不過需要一種機制來標記共享內存的讀寫狀態;也就是說要讓兩個進程知道:1)負責寫入的進程,必須知道當前共享內存是否可以寫入,上一次的寫入內容是否有被負責讀取的進程讀走;2)負責讀取的進程,必須知道當前共享內存是否需要讀取,防止重復讀取。一般的這種標記機制是通過以下方式來簡單實現:1)通過讀寫鎖來控制;2)共享內存上設置一個地方,專門存放當前共享內存的讀寫狀態;

D. linux pthread 信號量 佔用資源嗎

glibc提供的pthread互斥信號量可以用在進程內部,也可以用在進程間,可以在初始化時通過pthread_mutexattr_setpshared介面設置該信號量屬性,表示是進程內還是進程間。進程內的使用較為簡單,本文的總結主要是針對進程間的,進程內的也可以參考,其代碼實現原理是類似的。
一、實現原理
pthread mutex的實現是非常輕量級的,採用原子操作+futex系統調用。
在沒有競爭的情況下,即鎖空閑時,任務獲取信號量只需要通過原子操作鎖的狀態值,把值置為佔有,再記錄其他一些俄信息(owner,計數,如果使能回收功能則串入任務的信號量回收鏈表等),然後就返回了。
如果在獲取鎖時發現被佔用了,如果調用者需要睡眠等待,這時候會觸發futex系統調用,由內核繼續處理,內核會讓調用任務睡眠,並在適當時候喚醒(超時或者鎖狀態為可用)。
佔用鎖的任務釋放鎖時,如果沒有任務等待這把鎖,只需要把鎖狀態置為空閑即可。如果發現有其他任務在等待此鎖,則觸發futex系統調用,由內核喚醒等待任務。
由此可見,在沒有競爭的情況下,mutex只需要在用戶態操作鎖狀態值,無須陷入內核,是非常高效的。
獲取到鎖的任務沒有陷入內核,那麼當鎖支持優先順序翻轉時,高優先順序任務等待這把鎖,正常處理必須提升佔用鎖的任務優先順序。內核又是怎麼知道是哪個任務佔用了鎖呢?實現上,復用了鎖的狀態值,該值在空閑態時為0,非空閑態則保存了鎖的持有者ID,即PID,內核態通過PID就知道是那個任務了。
二、內核對鎖的管理
內核維護了一個hash鏈表,每把鎖都被插入到hash鏈表中去,hash值的計算如下(參考get_futex_key):1,如果是進程內的鎖,則通
過鎖的虛擬地址+任務mm指針值+鎖在頁內偏移;2,如果是進程間的鎖,則會獲取鎖虛擬地址對應物理地址的page描述符,由page描述符構造
hash值。
這樣計算的原因是進程間的鎖在各個進程內虛擬地址可能是不同的,但都映射到同一個物理地址,對應同一個page描述符。所以,內
核使用它來定位是否同一個鎖。
這里對進程間互斥鎖計算hash值的方法,給進程間共享鎖的使用設置了一個隱患條件。下面描述這個問題。

三、進程間互斥信號量的使用限制:必須在系統管理的內存上定義mutex結構,而不能在用戶reserved的共享內存上定義mutex結構。
鎖要實現進程間互斥,必須各個進程都能看到這個鎖,因此,鎖結構必須放在共享內存上。
獲取系統的共享內存通過System V的API介面創建:shmget, shmat,shmdt。但是shmget的參數需要一個id值,各進程映射同一塊共享內存需要同樣的ID值。如果各個進程需要共享的共享內存比較多,如幾千上萬個,ID值如果管理?shmget的man幫助和一些示例代碼給出的是通過ftok函數把一個文件轉為ID值(實際就是把文件對應的INODE轉為ID值),但實際應用中,如果需要的共享內存個數較多,難道創建成千上萬個文件來使用?而且怎麼保證文件在進程的生命周期內不會被刪除或者重建?
當時開發的系統還存在另外一種共享內存,就是我們通過remap_pfn_range實現的,自己管理了這塊內存的申請釋放。申請介面參數為字元串,相同的字元串表示同一塊內存。因此,傾向於使用自己管理的共享內存存放mutex結構。但在使用中,發現這種方法達不到互斥的效果。為什麼?
原因是自己管理的共享內存在內核是通過remap_pfn_range實現的,內核會把這塊內存置為reserved,表示非內核管理,獲取鎖的HASH值時,查找不到page結構,返回失敗了。最後的解決方法還是通過shmget申請共享內存,但不是通過ftok獲取ID,而是通過字元串轉為ID值並處理沖突。

四、進程間互斥信號量回收問題。
假設進程P1獲取了進程間信號量,異常退出了,還沒有釋放信號量,這時候其他進程想來獲取信號量,能獲取的到嗎?
或者進程P1獲取了信號量後,其他進程獲取不到進入了睡眠後,P1異常退出了,誰來負責喚醒睡眠的進程?
好在系統設計上已經考慮了這一點。
只要在信號量初始化時調用pthread_mutexattr_setrobust_np設置支持信號量回收機制,然後,在獲取信號量時,如果原來佔有信號量的進程退出了,系統將會返回EOWNERDEAD,判斷是這個返回值後,調用pthread_mutex_consistent_np完成信號量owner的切換工作即可。
其原理如下:
任務創建時,會注冊一個robust list(用戶態鏈表)到內核的任務控制塊TCB中期,獲取了信號量時,會把信號量掛入鏈表。進程復位時,內核會遍歷此鏈表(內核必須非常小心,因為此時的鏈表信息可能不可靠了,可不能影響到內核),置上ownerdead的標志到鎖狀態,並喚醒等待在此信號量鏈表上的進程。
五、pthread介面使用說明
pthread_mutex_init: 根據指定的屬性初始化一個mutex,狀態為空閑。
pthread_mutex_destroy: 刪除一個mutex
pthread_mutex_lock/trylock/timedlock/unlock: 獲取鎖、釋放鎖。沒有競爭關系的情況下在用戶態只需要置下鎖的狀態值即返回了,無須陷入內核。但是timedlock的入參為超時時間,一般需要調用系統API獲取,會導致陷入內核,性能較差,實現上,可先trylock,失敗了再timedlock。
pthread_mutexattr_init:配置初始化
pthread_mutexattr_destroy:刪除配置初始化介面申請的資源
pthread_mutexattr_setpshared:設置mutex是否進程間共享
pthread_mutexattr_settype:設置類型,如遞歸調用,錯誤檢測等。
pthread_mutexattr_setprotocol:設置是否支持優先順序翻轉
pthread_mutexattr_setprioceiling:設置獲取信號量的任務運行在最高優先順序。
每個set介面都有對應的get介面。

六、pthread結構變數說明

struct __pthread_mutex_s
{
int __lock; ----31bit:這個鎖是否有等待者;30bit:這個鎖的owner是否已經掛掉了。其他bit位:0鎖狀態空閑,非0為持有鎖的任務PID;
unsigned int __count; ----獲取鎖的次數,支持嵌套調用,每次獲取到鎖值加1,釋放減1。
int __owner; ----鎖的owner
unsigned int __nusers; ----使用鎖的任務個數,通常為1(被佔用)或0(空閑)
int __kind;----鎖的屬性,如遞歸調用,優先順序翻轉等。
int __spins; ----SMP下,嘗試獲取鎖的次數,盡量不進入內核。
__pthread_list_t __list; ----把鎖插入回收鏈表,如果支持回收功能,每次獲取鎖時要插入任務控制塊的回收鏈表。
}__data;

E. 關於linux 線程互斥鎖的問題,到底怎麼鎖的

首先初始化的鎖為全局變數,為所有線程共享,你一個線程得到鎖後自然而然就將其他線程阻塞了嘛,解鎖後其他線程才能獲取鎖,理解哪個鎖是一個阻塞性函數就ok,何必糾結呢,具體深挖掘的話就可以參照Linux環境高級編程了!

F. linux 共享內存 可不可以不加鎖呢 系統有兩個進程,一個負責寫入,一個負責讀取

Linux共享內存可以不用加鎖,不過需要一種機制來標記共享內存的讀寫狀態;
也就是說要讓兩個進程知道:
1)負責寫入的進程,必須知道當前共享內存是否可以寫入,上一次的寫入內容是否有被負責讀取的進程讀走;
2)負責讀取的進程,必須知道當前共享內存是否需要讀取,防止重復讀取。
一般的這種標記機制是通過以下方式來簡單實現:
1)通過讀寫鎖來控制;
2)共享內存上設置一個地方,專門存放當前共享內存的讀寫狀態;

G. linux中fcntl()函數的使用

前面的這5個基本函數實現了文件的打開、讀寫等基本操作,這一節將討論的是,在文 件已經共享的情況下如何操作,也就是當多個用戶共同使用、操作一個文件的情況,這時,Linux 通常採用的方法是給文件上鎖,來避免共享的資源產生競爭的狀態。
文件鎖包括建議性鎖和強制性鎖。
建議性鎖要求每個上鎖文件的進程都要檢查是否有鎖存,並且尊重已有的鎖。在一般情況下,內核和系統都不使用建議性鎖。強制性鎖是由內 核執行的鎖,當一個文件被上鎖進行寫入操作的時候,內核將阻止其他任何文件對其進行讀寫操作。採用強制性鎖對性能的影響很大,每次讀寫操作都必須檢查是否有鎖存在。
在 Linux 中,實現文件上鎖的函數有lock和fcntl,其中flock用於對文件施加建議性鎖,而fcntl不僅可以施加建議性鎖,還可以施加強制鎖。同時,fcntl還能對文件的某一記錄進行上鎖,也就是記錄鎖。
記錄鎖又可分為讀取鎖和寫入鎖,其中讀取鎖又稱為共享鎖,它能夠使多個進程都能在文件的同一部分建立讀取鎖。而寫入鎖又稱為排斥鎖,在任何時刻只能有一個進程在文件的某個部分上建立寫入鎖。當然,在文件的同一部分不能同時建立讀取鎖和寫入鎖。

H. linux自旋鎖使用時需要注意的幾個地方

1、在內核多線程編程時,為了保護共享資源通常需要使用鎖,而使用的比較多的就是spinlock,但需要注意的是:所有臨界區代碼都需要加鎖保護,否則就達不到保護效果。也就是,訪問共享資源的多個線程需要協同工作共同加鎖才能保證不出錯。在實際寫代碼時,有時候會網掉這一點,以致出現各種稀奇古怪的問題,而且很難找到原因。
2、在出現兩個和多個自旋鎖的嵌套使用時,務必注意加鎖和解鎖的順序。
比如:在線程1中,spinlock A -> spinlock B -> spin unlock B -> spin unlock A ;那麼,在需要同步的線程2中,若需要加相同的鎖,則順序也應該保持相同,spinlock A -> spinlock B -> spin unlock B -> spin unlock A ;否則,很有可能出現死鎖。
3、spinlock保護的代碼執行時間要盡量短,若有for循環之類的代碼,則一定要確保循環可以在短時間可以退出,從而使得spinlock可以釋放。
4、spinlock所保護的代碼在執行過程中不能睡眠。比如,在spinlock和spinunlock之間不能調用kmalloc, _from_user,kthread_stop等調用,因為這些函數調用均有可能導致線程睡眠。
5、spinlock在實際使用時有如下幾種類型,spin_lock,spin_lock_bh,spin_lock_irqsave。在具體使用時,需要根據被保護臨界區鎖處的上下文選擇合適的spinlock類型。
spin_lock用於不同cpu線程間同步,spin_lock_bh和spin_lock_irqsave主要用於本cpu線程間的同步,前者關軟中斷,後者關硬中斷。

I. linux c 如何實現進程間互斥呢

文件鎖/信號量,不要用進程共享鎖。

J. iuni系統怎麼把應用上鎖

文件鎖
1.fcntl()函數說明
前面講述的5個基本函數實現了文件的打開、讀/寫等基本操作,本節將討論在文件已經共享的情況下如何操作,也就是當多個用戶共同使用、操作一個文件的情況。這時,Linux通常採用的方法是給文件上鎖,來避免共享的資源產生競爭的狀態。
文件鎖包括建議性鎖和強制性鎖。建議性鎖要求每個上鎖文件的進程都要檢查是否有鎖存在,並且尊重已有的鎖。在一般情況下,內核和系統都不使用建議性鎖。強制性鎖是由內核執行的鎖,當一個文件被上鎖進行寫入操作時,內核將阻止其他任何文件對其進行讀寫操作。採用強制性鎖對性能的影響很大,每次讀寫操作都必須檢查是否有鎖存在。
在Linux中,實現文件上鎖的函數有lockf()和fcntl(),其中lockf()用於對文件施加建議性鎖,而fcntl()不僅可以施加建議性鎖,還可以施加強制性鎖。同時,fcntl()還能對文件的某一記錄上鎖,也就是記錄鎖。
記錄鎖又可分為讀取鎖和寫入鎖,其中讀取鎖又稱為共享鎖,它能夠使多個進程都能在文件的同一部分建立讀取鎖。而寫入鎖又稱為排斥鎖,在任何時刻只能有一個進程在文件的某個部分建立寫入鎖。當然,在文件的同一部分不能同時建立讀取鎖和寫入鎖。
fcntl()函數具有很豐富的功能,它可以對已打開的文件描述符進行各種操作,不僅包括管理文件鎖,還包括獲得設置文件描述符和文件描述符標志、文件描述符的復制等很多功能。本節主要介紹fcntl()函數建立記錄鎖的方法,關於它的其他操作,感興趣的讀者可以參看fcntl手冊。
2.fcntl()函數格式
用於建立記錄鎖的fcntl()函數語法要點如表2.6所示。

表2.6 fcntl()函數語法要點

所需頭文件
#include
<sys/types.h>
#include <unistd.h>
#include <fcntl.h>

函數原型
int fcntl(int fd, int cmd, struct flock
*lock)

函數傳入值
fd:文件描述符

cmd
F_DUPFD:復制文件描述符

F_GETFD:獲得fd的close-on-exec標志,若標志未設置,則文件經過exec()函數之後仍保持打開狀態

F_SETFD:設置close-on-exec標志,該標志由參數arg的FD_CLOEXEC位決定

F_GETFL:得到open設置的標志

F_SETFL:改變open設置的標志

F_GETLK:根據lock描述,決定是否上文件鎖

F_SETLK:設置lock描述的文件鎖

F_SETLKW:這是F_SETLK的阻塞版本(命令名中的W表示等待(wait))。
在無法獲取鎖時,會進入睡眠狀態;如果可以獲取鎖或者捕捉到信號則會返回

lock:結構為flock,設置記錄鎖的具體狀態,後面會詳細說明

函數返回值
成功:0
1:出錯

這里,lock的結構如下所示:

struct flock
{
short
l_type;
off_t l_start;
short l_whence;
off_t
l_len;
pid_t l_pid;
}
lock結構中每個變數的取值含義如表2.7所示。

表2.7 lock結構變數取值

l_type
F_RDLCK:讀取鎖(共享鎖)

F_WRLCK:寫入鎖(排斥鎖)

F_UNLCK:解鎖

l_start
加鎖區域在文件中的相對位移量(位元組),與l_whence值一起決定加鎖區域的起始位置

l_whence:
相對位移量的起點(同lseek的whence)

SEEK_SET:當前位置為文件的開頭,新位置為偏移量的大小

SEEK_CUR:當前位置為文件指針的位置,新位置為當前位置加上偏移量

SEEK_END:當前位置為文件的結尾,新位置為文件的大小加上偏移量的大小

l_len
加鎖區域的長度

為加鎖整個文件,通常的方法是將l_start設置為0,l_whence設置為SEEK_SET,l_len設置為0。
3.fcntl()使用實例
下面首先給出了使用fcntl()函數的文件記錄鎖功能的代碼實現。在該代碼中,首先給flock結構體的對應位賦予相應的值。
接著調用兩次fcntl()函數。用F_GETLK命令判斷是否可以進行flock結構所描述的鎖操作:若可以進行,則flock結構的l_type會被設置為F_UNLCK,其他域不變;若不可進行,則l_pid被設置為擁有文件鎖的進程號,其他域不變。
用F_SETLK和F_SETLKW命令設置flock結構所描述的鎖操作,後者是前者的阻塞版。
當第一次調用fcntl()時,使用F_GETLK命令獲得當前文件被上鎖的情況,由此可以判斷能不能進行上鎖操作;當第二次調用fcntl()時,使用F_SETLKW命令對指定文件進行上鎖/解鎖操作。因為F_SETLKW命令是阻塞式操作,所以,當不能把上鎖/解鎖操作進行下去時,運行會被阻塞,直到能夠進行操作為止。
文件記錄鎖的功能代碼具體如下所示:

/* lock_set.c */
int lock_set(int
fd, int type)
{
struct flock old_lock,
lock;
lock.l_whence = SEEK_SET;
lock.l_start =
0;
lock.l_len = 0;
lock.l_type =
type;
lock.l_pid = -1;

/* 判斷文件是否可以上鎖
*/
fcntl(fd, F_GETLK, &lock);
if (lock.l_type !=
F_UNLCK)
{
/* 判斷文件不能上鎖的原因 */
if
(lock.l_type == F_RDLCK) /* 該文件已有讀取鎖
*/
{
printf("Read lock already set by %d\n",
lock.l_pid);
}
else if (lock.l_type == F_WRLCK) /*
該文件已有寫入鎖 */
{
printf("Write lock already set
by %d\n", lock.l_pid);
}
}

/* l_type
可能已被F_GETLK修改過 */
lock.l_type = type;
/*
根據不同的type值進行阻塞式上鎖或解鎖 */
if ((fcntl(fd, F_SETLKW, &lock)) <
0)
{
printf("Lock failed:type = %d\n",
lock.l_type);
return
1;
}

switch(lock.l_type)
{
case
F_RDLCK:
{
printf("Read lock set by %d\n",
getpid());
}
break;
case
F_WRLCK:
{
printf("Write lock set by %d\n",
getpid());
}
break;
case
F_UNLCK:
{
printf("Release lock by %d\n",
getpid());
return
1;
}
break;
default:
break;
}/*
end of switch */
return 0;
}
下面的實例是文件寫入鎖的測試用例,這里首先創建了一個hello文件,之後對其上寫入鎖,最後釋放寫入鎖。代碼如下所示:

/* write_lock.c */
#include
<unistd.h>
#include <sys/file.h>
#include
<sys/types.h>
#include <sys/stat.h>
#include
<stdio.h>
#include <stdlib.h>
#include
"lock_set.c"

int main(void)
{
int
fd;

/* 首先打開文件 */
fd = open("hello",O_RDWR | O_CREAT,
0644);
if(fd < 0)
{
printf("Open file
error\n");
exit(1);
}

/* 給文件上寫入鎖
*/
lock_set(fd, F_WRLCK);
getchar();
/* 給文件解鎖
*/
lock_set(fd, F_UNLCK);
getchar();

close(fd);
exit(0);
}
為了能夠使用多個終端,更好地顯示寫入鎖的作用,本實例主要在PC上測試,讀者可將其交叉編譯,下載到目標板上運行。下面是在PC上的運行結果。為了使程序有較大的靈活性,筆者採用文件上鎖後由用戶輸入任意鍵使程序繼續運行。建議讀者開啟兩個終端,並且在兩個終端上同時運行該程序,以達到多個進程操作一個文件的效果。在這里,筆者首先運行終端一,請讀者注意終端二中的第一句。
終端一:

$ ./write_lock
write lock set by
4994
release lock by 4994
終端二:

$ ./write_lock
write lock already
set by 4994
write lock set by 4997
release lock by 4997
由此可見,寫入鎖為互斥鎖,同一時刻只能有一個寫入鎖存在。
接下來的程序是文件讀取鎖的測試用例,原理與上面的程序一樣。

/* fcntl_read.c */
#include
<unistd.h>
#include <sys/file.h>
#include
<sys/types.h>
#include <sys/stat.h>
#include
<stdio.h>
#include <stdlib.h>
#include
"lock_set.c"

int main(void)
{
int fd;
fd
= open("hello",O_RDWR | O_CREAT, 0644);
if(fd <
0)
{
printf("Open file
error\n");
exit(1);
}

/* 給文件上讀取鎖
*/
lock_set(fd, F_RDLCK);
getchar();
/* 給文件解鎖
*/
lock_set(fd, F_UNLCK);
getchar();

close(fd);
exit(0);
}
同樣開啟兩個終端,並首先啟動終端一上的程序,其運行結果如下所示。
終端一:

$ ./read_lock
read lock set by
5009
release lock by 5009
終端二:

$ ./read_lock
read lock set by
5010
release lock by 5010
讀者可以將此結果與寫入鎖的運行結果相比較,可以看出,讀取鎖為共享鎖,當進程5009已設置讀取鎖後,進程5010仍然可以設置讀取鎖。

閱讀全文

與共享鎖linux相關的資料

熱點內容
電子加密貨幣最新政策 瀏覽:377
androidcanvas撤銷 瀏覽:267
安卓手機怎麼把圖標全部下移 瀏覽:183
飢荒被伺服器踢出怎麼進 瀏覽:170
c編譯器哪款好 瀏覽:732
快手寶哥發明什麼app 瀏覽:822
張艷玲編譯 瀏覽:66
android展開收起動畫 瀏覽:237
linuxxz文件 瀏覽:160
在游戲中心裏面怎麼玩到解壓神器 瀏覽:484
電腦發到手機裡面照片怎麼解壓 瀏覽:73
虛擬pdf列印機64位 瀏覽:413
支付寶AES加密和解密 瀏覽:379
編譯實驗原理下載 瀏覽:131
加密防偽溯源系統私人定做 瀏覽:222
掃碼給電動車充電的app叫什麼 瀏覽:760
關閉命令提醒 瀏覽:356
雲賬本app伺服器 瀏覽:499
python輸入數字循環 瀏覽:370
未成年人用什麼app 瀏覽:517