linux系統的目錄/var/run下面一般我們都會看到很多的*.pid文件。而且往往新安裝的程序在運行後也會在/var/run目錄下面產生自己的pid文件。那麼這些pid文件有什麼作用呢?它的內容又是什麼呢?
(1) pid文件的內容:pid文件為文本文件,內容只有一行, 記錄了該進程的ID。
用
cat命令可以看到。
(2) pid文件的作用:防止進程啟動多個副本。只有獲得pid文件(固定路徑固定文件名)寫入權限(F_WRLCK)的進程才能正常啟動並把自身的PID寫入該文件中。其它同一個程序的多余進程則自動退出。
(3) 編程技巧:
調用fcntl設置pid文件的鎖定F_SETLK狀態,其中鎖定的標志位F_WRLCK。
如果成功鎖定,則寫入進程當前PID,進程繼續往下執行。
如果鎖定不成功,說明已經有同樣的進程在運行了,當前進程結束退出。
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &lock) < 0){
//鎖定不成功, 退出......
}
sprintf (buf, "%d\n", (int) pid);
pidsize = strlen(buf);
if ((tmp = write (fd, buf, pidsize)) != (int)pidsize){
//寫入不成功, 退出......
}
(4) 一些注意事項:
i) 如果進程退出,則該進程加的鎖自動失效。
ii) 如果進程關閉了該文件描述符fd, 則加的鎖失效。(整個進程運行期間不能關閉此文件描述符)
iii) 鎖的狀態不會被子進程繼承。如果進程關閉則鎖失效而不管子進程是否在運行。
(Locks are associated with processes. A process can only have one kind of lock set for each byte of a given
file. When any file descriptor for that file is closed by the process, all of the locks that process holds on that file are released, even if the locks were made using other descriptors that remain open. Likewise, locks are released when a process exits, and are not inherited by child processes created using fork.)
(5) 參考資料:
fcntl(文件鎖)
表頭文件 #include <unistd.h>
#include <fcntl.h>
函數定義int fcntl(int fd, int cmd, struct flock *lock);
函數解釋fd:文件描寫符
設置的文件描寫符,參數cmd代表欲壟斷的號召
F_DUPFD
復制參數fd的文件描寫符,厲行獲勝則歸來新復制的文件描寫符,
F_GETFD
獲得close-on-exec符號,若些符號的FD_CLOEXEC位為0,代表在調用
exec()相干函數時文件將不會關閉
F_SETFD 設置close-on-exec符號,該符號以參數arg的 FD_CLOEXEC位定奪
F_GETFL獲得open()設置的符號
F_SETFL改換open()設置的符號
F_GETLK獲得文件鎖定的事態,依據lock的描寫,定奪是否上文件鎖
F_SETLK設置文件鎖定的事態,此刻flcok,構造的l_tpye值定然是F_RDLCK、F_WRLCK或F_UNLCK,
萬一無法發生鎖定,則歸來-1
F_SETLKW 是F_SETLK的阻塞版本,在無法獲得鎖時會進去睡眠事態,萬一能夠獲得鎖可能捉拿到信號則歸來
參數lock指針為flock構造指針定義如下
struct flock {
...
short l_typejngaoy.com;
short l_whence;
off_t l_start; 鎖定區域的開關位置
off_t l_len; 鎖定區域的大小
pid_t l_pid; 鎖定動作的歷程
...
};
1_type有三種事態:
F_RDLCK讀取鎖(分享鎖)
F_WRLCK寫入鎖(排斥鎖)
F_UNLCK解鎖
l_whence也有三種措施
SEEK_SET以文件開始為鎖定的起始位置
SEEK_CUR以現在文件讀寫位置為鎖定的起始位置
SEEK_END以文件尾為鎖定的起始位置
歸來值 獲勝則歸來0,若有訛謬則歸來-1
l_len:加鎖區的長度
l_pid:具有阻塞目前歷程的鎖,其持有歷程的歷程號儲藏在l_pid中,由F_GETLK歸來
等閒是將l_start設置為0,l_whence設置為SEEK_SET,l_len設置為0