Linux 多程序鎖的幾種實現方案
阿新 • • 發佈:2021-06-23
我們知道,多執行緒可以用多執行緒互斥量pthread_mutex_t實現執行緒之間上鎖,那麼多程序之間如何共享鎖呢?
1. 檔案鎖實現多程序鎖
由於檔案鎖是存放到位於記憶體的系統檔案表中, 所有程序/執行緒可通過系統訪問。如果不同程序使用同一檔案鎖(寫鎖/排他鎖),當取得檔案鎖時,程序可繼續執行;如果沒有取得鎖,則阻塞等待。而唯一標識該檔案的是檔案路徑,因此,可以通過一個共同的檔案路徑,來實現多程序鎖機制。
參見檔案鎖的本質核心和原理 | CSDN
關鍵點:
1)建立/開啟一個唯一路徑的檔案;
2)P操作,取得檔案的寫鎖(排他鎖);V操作,釋放檔案的鎖;
static struct flock lock_it; /* 用於加鎖的flock物件 */ static struct unlock_it; /* 用於解鎖的flock物件 */ static int lock_fd = -1; void my_lock_init(char *pathname) { char lock_file[1024]; /* 存放檔名的臨時快取 */ /* 由於mkstemp會修改引數的最後6個字元,為避免pathname是字串常量,需要將字串從pathname copy到臨時快取lock_file中,然後作為建立唯一臨時檔案的引數 */ strncpy(lock_file, pathname, sizeof(lock_file)); lock_fd = mkstemp(lock_file); /* 建立唯一的臨時檔案並開啟 */ unlink(lock_file); /* 刪除指定檔名的檔案,如果有程序打開了該檔案,會在程序結束後所有指向該檔案的描述符都關閉後刪除檔案。這樣可以確保即使程式崩潰,臨時檔案也會完全消失 */ /* 設定flock物件的寫鎖屬性 */ lock_it.l_type = F_WRLCK; lock_it.l_whence = SEEK_SET; lock_it.l_start = 0; lock_it.l_len = 0; /* 設定flock物件的解鎖屬性 */ unlock_it.l_type = F_UNLCK; unlock_it.l_whence = SEEK_SET; unlock_it.l_start = 0; unlock_it.l_len = 0; } void my_lock_wait() { int rc; /* 取得寫鎖,如果阻塞等待時被中斷喚醒,則繼續恢復阻塞等待鎖資源 */ whilel ((rc = fcntl(lock_fd, F_SETLKW, &lock_it)) < 0) { if (errno == EINTR) continue; else err_sys("my_lock_wait fcntl error"); /* 如果沒有呼叫my_lock_init就直接呼叫fcntl,將會失敗 */ } } void my_lock_release() { if (fcntl(lock_fd, F_SETLKW, &unlock_it) < 0) err_sys("my_lock_release fcntl error"); }
2. 多執行緒鎖實現多程序鎖
多執行緒之間天然共享記憶體/變數,而多程序各有自己的程序空間,它們之間是不共享資料的
2個關鍵步驟
1)互斥鎖變數存放到共享記憶體;
2)設定互斥鎖變數的程序共享屬性(PTHREAD_PROCESS_SHARED);
static pthread_mutex_t *mptr; /* 互斥鎖變數指標,互斥鎖變數存放到共享記憶體 */ /** * 多程序互斥鎖變數初始化 */ void my_lock_init() { int fd; pthread_mutexattr_t mattr; /* 新建共享記憶體區域,但不對映到實際的普通檔案 */ fd = open("/dev/zero", O_RDWR, 0); if (fd < 0) err_sys("open error"); mptr = mmap(0, sizeof(pthread_mutex_t), PORT_READ | PORT_WRITE, MAP_SHARED, fd, 0); if (mptr == MAP_FAILED) err_sys("mmap"); if (close(fd)) err_sys("close error"); pthread_mutexattr_init(&mattr); pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED); phtread_mutex_init(mptr, &mattr); } /** * 加鎖 */ void my_lock_wait() { pthread_mutex_lock(mptr); } /** * 解鎖 */ void my_lock_release() { pthread_mutex_unlock(mptr); }