使用上儘管對第三者進行 locking ,或是避免使用 BufferI /O,不然容易出現資料不同步的現象,且跟 OS 的相依性會提高,對於要移值的程式就容易頭大啦!
開發與環境
Windows XP with SP3 + Dev-C++ v4.9.9.2 (gcc 3.4.2 )
FreeBSD 6.2-RELEASE-p1 (gcc 3.4.6)
程式碼:
#ifdef _WORK_FOR_WIN32_
#include <windows.h>
#include <io.h>
#endif
void File_LockByPtr( FILE * fd )
{
#ifndef _WORK_FOR_WIN32_
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
if( fcntl( fileno( fd ) , F_SETLKW , &fl ) < 0 )
{
perror("Lock File Pointer Error @ LockFilePtr");
exit(1);
}
#else
HANDLE hFile = (HANDLE)_get_osfhandle(_fileno( fd ));
OVERLAPPED ovl;
memset(&ovl, 0, sizeof(ovl));
if( LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ovl) == 0 )
{
perror("Lock File Pointer Error @ LockFilePtr");
exit(1);
}
#endif
}
void File_UnlockByPtr( FILE * fd )
{
#ifndef _WORK_FOR_WIN32_
struct flock fl;
#ifndef SYS_OPT_LOCKING_FILE_PONITER_WITHOUT_FFLUSH
fflush(fd);
#endif
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
if( fcntl( fileno( fd ) , F_SETLK , &fl ) < 0 )
{
perror("Unlock File Pointer Error @ UnlockFilePtr");
exit(1);
}
#else
HANDLE hFile = (HANDLE)_get_osfhandle(_fileno( fd ));
OVERLAPPED ovl;
memset(&ovl, 0, sizeof(ovl));
#ifndef SYS_OPT_LOCKING_FILE_PONITER_WITHOUT_FFLUSH
fflush( fd );
#endif
if( UnlockFileEx(hFile, 0, 1, 0, &ovl) == 0 )
{
perror("Unlock File Pointer Error @ UnlockFileByPtr");
exit(1);
}
#endif
}
void File_LockByFD( int fd )
{
#ifndef WIN32
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
if( fcntl( fd , F_SETLKW , &fl ) < 0 )
{
fprintf( stderr , "Lock File Pointer Error @ LockFilePtr\n");
exit(1);
}
#else
HANDLE hFile = (HANDLE)_get_osfhandle( fd );
OVERLAPPED ovl;
memset(&ovl, 0, sizeof(ovl));
if( ( lock_status = LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ovl) ) == 0 )
{
fprintf( stderr , "Lock File Pointer Error @ LockFileFD\n");
exit(1);
}
#endif
}
void File_UnlockByFD( int fd )
{
#ifndef WIN32
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = getpid();
if( fcntl( fd , F_SETLK , &fl ) < 0 )
{
fprintf( stderr , "Unlock File Pointer Error @ UnlockFilePtr\n");
exit(1);
}
#else
HANDLE hFile = (HANDLE)_get_osfhandle( fd );
OVERLAPPED ovl;
memset(&ovl, 0, sizeof(ovl));
if( UnlockFileEx(hFile, 0, 1, 0, &ovl) == 0 )
{
fprintf( stderr , "Unlock File Pointer Error @ UnlockFileByFD\n");
exit(1);
}
#endif
}
用法:
if( ( opt->dblock = fopen( lock_file , "w" ) ) == NULL )
{
fprintf( stderr , "Cannot Open Lock File @ DB_Lock\n" );
exit(1);
}
File_LockByPtr( opt->dblock );
...
File_UnlockByPtr( opt->dblock );
fclose(opt->dblock);
或
#ifndef WIN32
struct flock fl;
if( ( db_lock_fd = open( db_lock_file , O_RDWR | O_CREAT ) ) == -1 )
#else
HANDLE hFile;
OVERLAPPED ovl;
if( ( db_lock_fd = _open( db_lock_file , _O_RDWR | _O_CREAT , _S_IREAD| _S_IWRITE ) ) == -1 )
#endif
{
switch( errno )
{
case EACCES:
printf("Tried to open read-only file for writing, file's sharing mode does not allow specified operations, or given path is directory.\n");
break;
case EEXIST:
printf("_O_CREAT and _O_EXCL flags specified, but filename already exists.\n");
break;
case EINVAL:
printf("Invalid oflag or pmode argument.\n");
break;
case EMFILE:
printf("No more file descriptors available (too many open files).\n");
break;
case ENOENT:
printf("File or path not found.\n");
break;
}
fprintf( stderr , "Cannot Open Lock File @ db_lock ,%d, %s\n" , errno , db_lock_file );
exit(1);
}
File_LockByFD( db_lock_fd );
...
File_UnlockByFD( db_lock_fd );
沒有留言:
張貼留言