当前位置: 技术问答>linux和unix
关于LINUX下进程和线程对文件的同步问题,请高手来看看!!!
来源: 互联网 发布时间:2015-04-30
本文导语: 不知道大家有没有碰到过这样的问题,即在LINUX下的程序有时候会碰到多个进程访问同一个文件, 以及一个进程的不同线程对一个文件的同步问题,我尝试用了系统提供的fcntl函数来给文件加锁, 但是这只是一个进程...
不知道大家有没有碰到过这样的问题,即在LINUX下的程序有时候会碰到多个进程访问同一个文件,
以及一个进程的不同线程对一个文件的同步问题,我尝试用了系统提供的fcntl函数来给文件加锁,
但是这只是一个进程互斥锁,对于多线程的访问,后面的操作会覆盖前面的,看了stevens大爷的
网络编程的第9章中的my_lock和my_unlock的例子,还是不能很好的解决多线程同步的问题,
而他在11章利用信号灯对两个函数的另一种实现在LINUX下不行,因为LINUX下不支持有名信号灯,
哪位大虾能给提供一个比较好的解决方法,能给提供源代码的(上面两个函数的)我再加300分!
以及一个进程的不同线程对一个文件的同步问题,我尝试用了系统提供的fcntl函数来给文件加锁,
但是这只是一个进程互斥锁,对于多线程的访问,后面的操作会覆盖前面的,看了stevens大爷的
网络编程的第9章中的my_lock和my_unlock的例子,还是不能很好的解决多线程同步的问题,
而他在11章利用信号灯对两个函数的另一种实现在LINUX下不行,因为LINUX下不支持有名信号灯,
哪位大虾能给提供一个比较好的解决方法,能给提供源代码的(上面两个函数的)我再加300分!
|
如果使用进程间同步,使用IPC(信号量(SYS-V)、消息队列(SYS-V)、SOCKET)都行
如果使用线程同步,建议使用posix 信号量和消息队列
这些都没问题,如果不能实现文件互斥,那么最大可能是你设计的文件互斥逻辑可能存在问题
如果使用线程同步,建议使用posix 信号量和消息队列
这些都没问题,如果不能实现文件互斥,那么最大可能是你设计的文件互斥逻辑可能存在问题
|
/* recordio */
#include
#include
#include
#include
#include "recordio.h"
int initrecord(const char* pathname, unsigned int reclen)
{
int fd;
int rs;
RECORDINFO info;
if ( (fd = open(pathname, O_RDWR|O_CREAT, 0660)) == -1 ) {
perror("Fail to open file for initializing record");
return -1;
}
if ( (rs = read(fd, &info, sizeof(RECORDINFO))) == -1 ) {
perror("Fail to read record info for initializing record");
return -1;
}
if ( rs == 0 ) {
info.reclen = reclen;
info.recnum = 0;
if ( write(fd, &info, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to write record info for initializing record");
return -1;
}
}
close(fd);
return 0;
}
int addrecord(const char* pathname, void* buf, unsigned int reclen, unsigned int recnum)
{
int fd;
int rs;
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
if ( (fd = open(pathname, O_WRONLY|O_APPEND)) == -1 ) {
perror("Fail to open file for adding record");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to lock file for adding record");
return -1;
}
lock.l_type = F_UNLCK;
rs = write(fd, buf, reclen * recnum);
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to unlock file for adding record");
return -1;
}
close(fd);
return rs;
}
int getrecord(const char* pathname, void* buf, unsigned int reclen, unsigned int recnum)
{
int fd;
int len;
RECORDINFO info;
struct flock lock;
lock.l_type = F_WRLCK;
lock.l_start = 0;
lock.l_whence = SEEK_SET;
lock.l_len = 0;
if ( (fd = open(pathname, O_RDWR)) == -1 ) {
perror("Fail to open file for geting record");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to lock file for geting record");
return -1;
}
lock.l_type = F_UNLCK;
if ( read(fd, &info, sizeof(RECORDINFO)) != sizeof(RECORDINFO) ) {
perror("Fail to read record info");
return -1;
}
if ( info.reclen != reclen ) {
fprintf(stderr, "Invalid reclen parameter n");
return -1;
}
if ( lseek(fd, sizeof(RECORDINFO) + info.reclen * info.recnum, SEEK_SET) == -1 ) {
perror("Fail to seek read position");
return -1;
}
if ( (len = read(fd, buf, reclen * recnum)) == -1 ) {
perror("Fail to get record");
return -1;
}
if ( len == 0 ) {
if ( ftruncate(fd, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to truncate file");
return -1;
}
info.recnum = 0;
if ( lseek(fd, 0, SEEK_SET) == -1 ) {
perror("Fail to return beginning");
return -1;
}
if ( write(fd, &info, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to update record info");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to unlock file for geting record");
return -1;
}
close(fd);
return 0;
} else {
info.recnum += len / info.reclen;
if ( lseek(fd, 0, SEEK_SET) == -1 ) {
perror("Fail to return beginning");
return -1;
}
if ( write(fd, &info, sizeof(RECORDINFO)) == -1 ) {
perror("Fail to update record info");
return -1;
}
if ( fcntl(fd, F_SETLKW, &lock) == -1 ) {
perror("Fail to unlock file for geting record");
return -1;
}
close(fd);
return len;
}
}