fopen 系统会自动分配缓存,读取文件需要的io次数会变少,速度更快
不过很不幸的是会有多进程或者多线程的错乱问题,因此需要加锁保证执行正确
常用锁方式:flock,fcntl,lockf
lock.l_type = F_WRLCK; //F_RDLCK(读方式加锁) 、F_WRLCK(写方式加锁) 、F_UNLCK(解锁)
lock.l_whence = 0; //从文件起始位置开始
lock.l_start = 0; //偏移值为0
lock.l_len = 0; //整篇加锁
fcntl(fd,F_SETLK,&lock),“读共享、写独占”特性,函数返回errno,
F_SETLK和F_SETLKW 用于加锁解锁wait阻塞,F_GETLK实际上是用于获取文件锁的相关信息
int flock(int fd,int operation);flock(fp->_fileno, LOCK_EX),LOCK_EX 建立互斥锁定,LOCK_UN 解除文件锁定
进程线程测试程序:
http://blog.chinaunix.net/uid-20682147-id-76327.html
#include<stdio.h>
#include<string>
using namespace std;
int main(void)
{
FILE *fp=NULL;
fp=fopen("hello","w+");
if(NULL==fp)
{
return -1;
}
int temp=3333333;
char s[] = "helloword";
fprintf(fp," %s %d %f %c " ,s, temp, 22.22, 'a');
char str[] = "This is runoob.com";
fwrite(str, sizeof(str) , 1, fp);
//fflush(fp);
//fclose(fp);
//fp = fopen("hello","r");
fseek(fp, 0, SEEK_SET);
char buffer[90] = {0};
fread(buffer, 90, 1, fp);
printf("fread : %s\n", buffer);
fseek(fp, 0, SEEK_SET);
char c;
while(1)
{
c = fgetc(fp);
if( feof(fp) )
{
break ;
}
printf("%c", c);
}
fclose(fp);
//system("type hello");
fp=NULL;
return 0;
}
// 文件锁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可以只加锁文件的指定部分
#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 x x.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;
}