C linux下如何创建带超时的文件锁
我试图锁定linux下多个应用程序访问的一些关键资源 所有应用程序在进入关键部分时将调用同一文件上的acquireLock函数,在离开时调用releaseLock函数。 如果超过一段时间未获得锁,则调用方将继续执行其他操作 下面的代码在进程较慢的情况下工作,但在压力下锁很容易被打破锁是由多个进程获得的,所以我想我在某个地方遇到了竞争条件 有人能告诉我为什么它不起作用,正确的实现方式是什么吗 非常感谢 MVC linux下如何创建带超时的文件锁,c,linux,multithreading,C,Linux,Multithreading,我试图锁定linux下多个应用程序访问的一些关键资源 所有应用程序在进入关键部分时将调用同一文件上的acquireLock函数,在离开时调用releaseLock函数。 如果超过一段时间未获得锁,则调用方将继续执行其他操作 下面的代码在进程较慢的情况下工作,但在压力下锁很容易被打破锁是由多个进程获得的,所以我想我在某个地方遇到了竞争条件 有人能告诉我为什么它不起作用,正确的实现方式是什么吗 非常感谢 MV #包括 #包括 #包括 #包括 #包括 #包括 #包括 //***************
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//************************************************************
#定义CYCLETIME 1000
//************************************************************
//************************************************************
int acquireLock(char*lockFile,int msTimeout)
{
int lockFd;
int cntTimeout=0;
如果((lockFd=open(lockFile,O|u CREAT | O| u RDWR,S|u IRWXU | S|IRWXG | S|u IRWXO))<0)
返回-1;
而(群集(锁定FD,锁定EX |锁定NB)<0){
usleep(周期时间);
cntTimeout++;
如果(CNTTEOUT>=msTimeout){
返回-1;
}
}
返回锁fd;
}
//*************************************************************
无效释放锁(内部锁FD)
{
鸥群(lockFd,LOCK_UN);
关闭(锁定FD);
}
//************************************************************
看来错误在代码的另一部分,锁按预期工作
我分享我正在使用的代码,以防它对其他人有帮助
这些是锁定功能:
/* ----------------------------------------------------------------------- *
* Code derived by the flock.c in the "util-linux" ubuntu package
* by Peter Anvin
* ----------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/file.h>
#include <sys/time.h>
#include <signal.h>
//************************************************************
static sig_atomic_t timeout_expired = 0;
//************************************************************
static void timeout_handler(int sig)
{
(void)sig;
timeout_expired = 1;
}
//************************************************************
int acquireLock(char *lockFile, int msTimeout)
{
struct itimerval timeout, old_timer;
struct sigaction sa, old_sa;
int err;
int sTimeout = msTimeout/1000;
memset(&timeout, 0, sizeof timeout);
timeout.it_value.tv_sec = sTimeout;
timeout.it_value.tv_usec = ((msTimeout-(sTimeout*1000))*1000);
memset(&sa, 0, sizeof sa);
sa.sa_handler = timeout_handler;
sa.sa_flags = SA_RESETHAND;
sigaction(SIGALRM, &sa, &old_sa);
setitimer(ITIMER_REAL, &timeout, &old_timer);
int lockFd;
int cntTimeout = 0;
if ((lockFd = open(lockFile, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO)) < 0)
return -1;
while (flock(lockFd, LOCK_EX))
{
switch( (err = errno) ) {
case EINTR: /* Signal received */
if ( timeout_expired )
setitimer(ITIMER_REAL, &old_timer, NULL); /* Cancel itimer */
sigaction(SIGALRM, &old_sa, NULL); /* Cancel signal handler */
return -1; /* -w option set and failed to lock */
continue; /* otherwise try again */
default: /* Other errors */
return -1;
}
}
setitimer(ITIMER_REAL, &old_timer, NULL); /* Cancel itimer */
sigaction(SIGALRM, &old_sa, NULL); /* Cancel signal handler */
return lockFd;
}
//***************************************************************
void releaseLock (int lockFd)
{
flock(lockFd, LOCK_UN);
close(lockFd);
}
//************************************************************
/*--------------------------------------------------------------------------------------*
*“util linux”ubuntu包中flock.c派生的代码
*彼得·安文
* ----------------------------------------------------------------------- */
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//************************************************************
静态信号原子超时过期=0;
//************************************************************
静态无效超时处理程序(int sig)
{
(无效)sig;
超时时间=1;
}
//************************************************************
int acquireLock(char*lockFile,int msTimeout)
{
结构itimerval超时,旧计时器;
结构sigaction sa,old_sa;
INTERR;
int sTimeout=msTimeout/1000;
memset(&timeout,0,sizeof timeout);
timeout.it_value.tv_sec=刺激;
timeout.it_value.tv_usec=((msTimeout-(sTimeout*1000))*1000);
memset(&sa,0,sizeof sa);
sa.sa_handler=超时_handler;
sa.sa_flags=sa_RESETHAND;
sigaction(SIGALRM、sa和old_sa);
setitimer(ITIMER\U REAL、超时和旧定时器);
int lockFd;
int cntTimeout=0;
如果((lockFd=open(lockFile,O|u CREAT | O| u RDWR,S|u IRWXU | S|IRWXG | S|u IRWXO))<0)
返回-1;
while(flock(lockFd,LOCK_EX))
{
开关((err=errno)){
案例EINTR:/*接收到信号*/
如果(超时\u已过期)
setitimer(ITIMER\u REAL和old\u timer,NULL);/*取消ITIMER*/
sigaction(SIGALRM和old_sa,NULL);/*取消信号处理程序*/
返回-1;/*-w选项集,无法锁定*/
继续;/*否则重试*/
默认值:/*其他错误*/
返回-1;
}
}
setitimer(ITIMER\u REAL和old\u timer,NULL);/*取消ITIMER*/
sigaction(SIGALRM和old_sa,NULL);/*取消信号处理程序*/
返回锁fd;
}
//***************************************************************
无效释放锁(内部锁FD)
{
鸥群(lockFd,LOCK_UN);
关闭(锁定FD);
}
//************************************************************
。。。这些可以通过读写FIFO来尝试
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "lock.h"
#define LOCKED 1
void main(int argc, char **argv)
{
const char *filename;
const char *fifo_name;
const char *message;
int lockfd, fifoHandle;
filename = argv[1];
fifo_name = argv[2];
message = argv[3];
char bufin[1024];
char bufout[1024];
struct stat st;
int bufsize = strlen(message)+1;
int sleeptime = 0;
int j = 0;
if (stat(fifo_name, &st) != 0)
mkfifo(fifo_name, 0666);
while (1){
if (LOCKED)
lockfd=acquireLock(filename, 15000);
if (lockfd==-1)
printf("timeout expired \n");
fifoHandle= open(fifo_name, O_RDWR);
strcpy(bufin, message);
bufin[bufsize-1] = 0x0;
write(fifoHandle, bufin, sizeof(char)*bufsize);
sleeptime = rand() % 100000;
usleep(sleeptime);
read(fifoHandle, &bufout, sizeof(char)*(bufsize+1));
printf("%s - %d \n", bufout, j);
j= j+1;
if (LOCKED)
releaseLock(lockfd);
sleeptime = rand() % 10000;
}
unlink(fifo_name);
return;
}
#包括
#包括
#包括
#包括
#包括“lock.h”
#定义锁定1
void main(整型argc,字符**argv)
{
常量字符*文件名;
常量字符*fifo_名称;
const char*消息;
国际洛克菲德,第五把手;
filename=argv[1];
fifo_name=argv[2];
message=argv[3];
char-bufin[1024];
char bufout[1024];
结构统计;
int bufsize=strlen(消息)+1;
int sleeptime=0;
int j=0;
如果(统计(fifo_名称和st)!=0)
mkfifo(fifo_名称,0666);
而(1){
如果(已锁定)
lockfd=acquireLock(文件名,15000);
如果(lockfd==-1)
printf(“超时已过期\n”);
fifo句柄=打开(fifo\u名称,O\u RDWR);
strcpy(bufin,消息);
bufin[bufsize-1]=0x0;
写入(fifoHandle、bufin、sizeof(char)*bufsize);
sleeptime=rand()%100000;
usleep(睡眠时间);
读取(fifoHandle和bufout,sizeof(char)*(bufsize+1));
printf(“%s-%d\n”,bufout,j);
j=j+1;
如果(已锁定)
释放锁(lockfd);
sleeptime=rand()%10000;
}
取消链接(fifo_名称);
返回;
}
通过发送两个终端
./locktestFIFO./lck./fifo消息a
./locktestFIFO./lck./fifo消息b
如果未将LOCKED设置为1,则消息将混淆,否则两个线程将正确获取并释放资源。它以何种方式断开?它是否只有在超时后才会中断?要同步某些资源的使用,无论是其逻辑资源还是物理资源,还有其他同步方法。@David,编辑了问题,锁是由多个进程获得的。您能给我们提供足够的代码来复制该问题吗?您所声称的特定故障模式似乎是不可能的。@David是的,我将尝试编写一个示例
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "lock.h"
#define LOCKED 1
void main(int argc, char **argv)
{
const char *filename;
const char *fifo_name;
const char *message;
int lockfd, fifoHandle;
filename = argv[1];
fifo_name = argv[2];
message = argv[3];
char bufin[1024];
char bufout[1024];
struct stat st;
int bufsize = strlen(message)+1;
int sleeptime = 0;
int j = 0;
if (stat(fifo_name, &st) != 0)
mkfifo(fifo_name, 0666);
while (1){
if (LOCKED)
lockfd=acquireLock(filename, 15000);
if (lockfd==-1)
printf("timeout expired \n");
fifoHandle= open(fifo_name, O_RDWR);
strcpy(bufin, message);
bufin[bufsize-1] = 0x0;
write(fifoHandle, bufin, sizeof(char)*bufsize);
sleeptime = rand() % 100000;
usleep(sleeptime);
read(fifoHandle, &bufout, sizeof(char)*(bufsize+1));
printf("%s - %d \n", bufout, j);
j= j+1;
if (LOCKED)
releaseLock(lockfd);
sleeptime = rand() % 10000;
}
unlink(fifo_name);
return;
}