-
// 文件锁flock、lockf和fcntl区别测试程序:
-
// 1) flock是系统调用,为System V锁
-
// 2) fcntl是系统调用,lockf是基于fcntl实现的libc库函数,为posix锁
-
// 3) flock可以同时用于多线程和多进程互斥(x86 Linux验证)
-
// 4) 而lockf和fcntl只能用于多进程
-
// 5) 对于NFS,只能使用fcntl,而flock只能用于本地文件系统
-
// 6) flock只是建议性锁
-
// 7) fcntl可以实现强制性锁
-
// 8) flock只能对整个文件加锁
-
// 9) fcntl和lockf可以只加锁文件的指定部分
-
// 10) flock锁不会被fork出的子进程继承,对于dup得到的fd是递归的,对于open得到的fd是非递归的
-
// 11) fcntl锁会被fork出的子进程继承,对于open得到的fd是递归的
-
// 12) flock和file table entry相关,而不是fd
-
// 13) flock和fcntl锁互不影响,可同时时对同一个文件上锁,而不会死锁
-
#include <fcntl.h>
-
#include <pthread.h>
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include <string>
-
#include <sys/types.h>
-
#include <sys/stat.h>
-
#include <sys/file.h>
-
#include <sys/wait.h>
-
#include <unistd.h>
-
// 查看锁信息: cat /proc/locks
-
// 编译方法: g++ -g -o file_lock file_lock.cpp -pthread -DX=3 -DZ=2
-
// 宏X控制是使用flock、lockf还是fcntl文件锁,值为1使用flock,值为2使用lockf,值为3使用fcntl
-
// 宏Z控制是多线程还是多进程,值为1为多线程模式,值为2为多进程模式
-
-
// 取当前时间,但不包括日期部分
-
std::string now()
-
{
-
time_t t = time(NULL);
-
struct tm tm;
-
localtime_r(&t, &tm);
-
char buf[sizeof("22:49:22")];
-
snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
-
return buf;
-
}
-
-
#if X==1 // flock
-
int lock(const char* file)
-
{
-
int fd = open(file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
-
if (-1 == fd)
-
{
-
printf("open error: %m\n");
-
exit(1);
-
}
-
-
if (-1 == flock(fd, LOCK_EX))
-
{
-
printf("flock error: %m\n");
-
close(fd);
-
exit(1);
-
}
-
return fd;
-
}
-
-
void unlock(int fd)
-
{
-
flock(fd, LOCK_UN);
-
close(fd);
-
}
-
-
#elif X == 2 // lockf
-
int lock(const char* file)
-
{
-
int fd = open(file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
-
if (-1 == fd)
-
{
-
printf("open error: %m\n");
-
exit(1);
-
}
-
-
lseek(fd,0L,0);
-
if (-1 == lockf(fd, F_LOCK, 0L))
-
{
-
printf("lockf error: %m\n");
-
exit(1);
-
}
-
return fd;
-
}
-
-
void unlock(int fd)
-
{
-
lseek(fd,0L,0);
-
lockf(fd, F_ULOCK, 0);
-
close(fd);
-
}
-
-
#elif X==3 // fcntl
-
int lock(const char* file)
-
{
-
int fd = open(file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
-
if (-1 == fd)
-
{
-
printf("open error: %m\n");
-
exit(1);
-
}
-
-
struct flock f;
-
f.l_whence = SEEK_SET;
-
f.l_start = 0;
-
f.l_len = 0;
-
f.l_type = F_WRLCK;
-
f.l_pid = getpid();
-
lseek(fd,0L,0);
-
if (-1 == fcntl(fd, F_SETLKW, &f))
-
{
-
printf("fcntl error: %m\n");
-
exit(1);
-
}
-
-
return fd;
-
}
-
-
void unlock(int fd)
-
{
-
struct flock f;
-
f.l_whence = SEEK_SET;
-
f.l_start = 0;
-
f.l_len = 0;
-
f.l_type = F_UNLCK;
-
f.l_pid = getpid();
-
lseek(fd,0L,0);
-
fcntl(fd, F_SETLKW, &f);
-
close(fd);
-
}
-
#endif
-
-
void* thread1(void* param)
-
{
-
printf("[%u][%s] to sleep 2\n", pthread_self(), now().c_str());
-
sleep(2);
-
-
printf("[%u][%s] to lock\n", pthread_self(), now().c_str());
-
const char* file = (const char*)param;
-
int fd = lock(file);
-
printf("[%u][%s] locked\n", pthread_self(), now().c_str());
-
-
unlock(fd);
-
printf("[%u][%s] unkock and exit\n", pthread_self(), now().c_str());
-
return NULL;
-
}
-
-
void* thread2(void* param)
-
{
-
printf("[%u][%s] to lock\n", pthread_self(), now().c_str());
-
const char* file = (const char*)param;
-
int fd = lock(file);
-
printf("[%u][%s] locked and sleep 6\n", pthread_self(), now().c_str());
-
-
sleep(6);
-
unlock(fd);
-
printf("[%u][%s] unkock and exit\n", pthread_self(), now().c_str());
-
return NULL;
-
}
-
-
int main(int argc, char* argv[])
-
{
-
const char* file = "abc";
-
#if X==1
-
printf("flock mode\n");
-
#elif X==2
-
printf("lockf mode\n");
-
#elif X==3
-
printf("fcntl mode\n");
-
#endif
-
-
#if Z==1 // 多线程模式
-
printf("thread mode\n");
-
-
pthread_t th1, th2;
-
pthread_create(&th1, NULL, thread1, const_cast<char*>(file));
-
pthread_create(&th2, NULL, thread2, const_cast<char*>(file));
-
-
pthread_join(th1, NULL);
-
pthread_join(th2, NULL);
-
-
#else // 多进程模式
-
printf("process mode\n");
-
-
pid_t pid1 = fork();
-
if (0 == pid1)
-
{
-
printf("[%u][%s] to sleep 2\n", getpid(), now().c_str());
-
sleep(2);
-
-
printf("[%u][%s] to lock\n", getpid(), now().c_str());
-
int fd = lock(file);
-
printf("[%u][%s] locked\n", getpid(), now().c_str());
-
unlock(fd);
-
printf("[%u][%s] unkock and exit\n", getpid(), now().c_str());
-
exit(0);
-
}
-
-
pid_t pid2 = fork();
-
if (0 == pid2)
-
{
-
printf("[%u][%s] to lock\n", getpid(), now().c_str());
-
int fd = lock(file);
-
printf("[%u][%s] locked and sleep 6\n", getpid(), now().c_str());
-
-
sleep(6);
-
unlock(fd);
-
printf("[%u][%s] unkock and exit\n", getpid(), now().c_str());
-
exit(0);
-
}
-
-
waitpid(pid1, NULL, 0);
-
waitpid(pid2, NULL, 0);
-
#endif
-
-
return 0;
-
}
阅读(881) | 评论(0) | 转发(0) |