1. 程式人生 > >Linux檔案鎖flock,檢查程式是否已經執行

Linux檔案鎖flock,檢查程式是否已經執行

在多個程序同時操作同一份檔案的過程中,很容易導致檔案中的資料混亂,需要鎖操作來保證資料的完整性,這裡介紹的針對檔案的鎖,稱之為“檔案鎖”-flock。 flock,建議性鎖,不具備強制性。一個程序使用flock將檔案鎖住,另一個程序可以直接操作正在被鎖的檔案,修改檔案中的資料,原因在於flock只是用於檢測檔案是否被加鎖,針對檔案已經被加鎖,另一個程序寫入資料的情況,核心不會阻止這個程序的寫入操作,也就是建議性鎖的核心處理策略。 flock主要三種操作型別:      LOCK_SH,共享鎖,多個程序可以使用同一把鎖,常被用作讀共享鎖;      LOCK_EX,排他鎖,同時只允許一個程序使用,常被用作寫鎖;      LOCK_UN,釋放鎖; 程序使用flock嘗試鎖檔案時,如果檔案已經被其他程序鎖住,程序會被阻塞直到鎖被釋放掉,或者在呼叫flock的時候,採用LOCK_NB引數,在嘗試鎖住該檔案的時候,發現已經被其他服務鎖住,會返回錯誤,errno錯誤碼為EWOULDBLOCK。即提供兩種工作模式:阻塞與非阻塞型別。 服務會阻塞等待直到鎖被釋放: flock(lockfd,LOCK_EX) 服務會返回錯誤發現檔案已經被鎖住時: ret  = flock(lockfd,LOCK_EX|LOCK_NB) 同時ret = -1, errno = EWOULDBLOCK  flock鎖的釋放非常具有特色,即可呼叫LOCK_UN引數來釋放檔案鎖,也可以通過關閉fd的方式來釋放檔案鎖(flock的第一個引數是fd),意味著flock會隨著程序的關閉而被自動釋放掉。同時由於damon程序生成時會繼承fd。故此方法有一定的侷限性。 flock其中的一個使用場景為:檢測程序是否已經存在;
int checkexit(char* pfile){
     if (pfile == NULL)
          return -1;
     int lockfd = open(pfile,O_RDWR);
     if (lockfd == -1)
          return -2;
     int iret = flock(lockfd,LOCK_EX|LOCK_NB)
     if (iret == -1)
          return -3;
     return 0;

}

example 1
#define FILE_NAME "/tmp/filelock"
#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
int main(int argc , char *agvv[])
{
	int fd;
	fd = open(FILE_NAME,O_CREAT|O_RDWR,0666);
	if( fd == -1)
		return -1;
	int ret = flock(fd,LOCK_EX|LOCK_NB);
	if(ret == 0)
	{
		printf("first run!\n");
		sleep(10);
	}else{
		printf("already run!\n");
	}

	return 0;
}
但是使用以上檔案鎖,會將鎖同時傳遞給子程序或者是由此程序fork出來的deamon程序。此時如果想使用檢查程式是否已經存在的方法,就要使用另外一種檔案鎖。 example2
#define FILE_NAME "/tmp/filelock"
#include <stdio.h>
#include <unistd.h>
#include <sys/file.h>
int Lockfile(const int iFd)
{
	struct flock    stLock;

	stLock.l_type = F_WRLCK;        /* F_RDLCK, F_WRLCK, F_UNLCK */
	stLock.l_start = 0;    /* byte offset, relative to l_whence */
	stLock.l_whence = SEEK_SET;    /* SEEK_SET, SEEK_CUR, SEEK_END */
	stLock.l_len = 0;        /* #bytes (0 means to EOF) */

	return (fcntl(iFd, F_SETLK, &stLock));
}
int main(int argc , char *agvv[])
{
	int fd;
	fd = open(FILE_NAME,O_CREAT|O_RDWR,0666);
	if( fd == -1)
		return -1;
	int ret = Lockfile(fd);
	if(ret == 0)
	{
		printf("first run!\n");
		sleep(10);
	}else{
		printf("already run!\n");
	}

	return 0;
}