Windows可以select打开具有独占访问权限的文件。 Unix没有。
为了确保对某些文件或设备的独占访问,Unix中通常使用通常存储在/ var / lock目录中的locking文件。
如果locking文件已经存在,则C指令open( "/var/lock/myLock.lock", O_RDWR | O_CREAT | O_EXCL, 0666 )
将返回-1,否则将创build它。 该函数是primefaces的,并确保没有竞争条件。
当资源被释放时,locking文件被删除,如下面的指令remove( "/var/lock/myLock.lock" )
。
这个方法有两个问题。
该程序可能会终止而不会取消locking。 例如,因为它被杀死,崩溃或其他。 locking文件保持原状,即使不再使用,也会阻止访问资源。
locking文件是使用组和世界写入权限创build的,但通常会将帐户configuration为使用将清除组和世界写入权限的权限掩码。 因此,如果我们有一个可靠的方法来确定该锁是孤立的(不使用),不是文件的所有者的用户将不被允许删除它。
为了logging,我使用locking文件来确保独占访问连接到串行端口的设备(实际上是/ dev / ttyUSBx)。 咨询方法,需要合作,没关系。 但是不同用户之间应该保证独占访问。
有没有比locking文件更好的同步方法? 如何确定创build锁文件的进程是否仍在运行? 如何使其他用户可以删除locking文件,如果不使用?
我提出的一个解决scheme是使用该文件作为Unix套接字文件。 如果文件存在,请尝试使用该文件进行连接。 如果失败,我们可能会认为文件的所有者进程已经死亡。 这需要在拥有者进程中的socket accept()
上有一个线程循环。 不幸的是,这个系统不再是primefaces。
你可能应该使用flock()
,如
fd = open(filename, O_RDWR | O_CREAT, 0666); // open or create lockfile //check open success... rc = flock(fd, LOCK_EX | LOCK_NB); // grab exclusive lock, fail if can't obtain. if (rc) { // fail }
看看启发性的演示文件锁定技巧和陷阱 :
这个简短的演讲介绍了文件锁定的几个常见缺陷,以及更有效地使用文件锁定的一些有用的技巧。
编辑:更准确地解决您的问题:
有没有比锁定文件更好的同步方法?
正如@Hasturkun已经提到,正如上面的介绍所告诉的,系统调用你需要使用的是flock(2)
。 如果您希望在许多用户中共享的资源已经基于文件(在您的情况下是/dev/ttyUSBx
),那么您可以将设备文件自身 /dev/ttyUSBx
。
如何确定创建锁文件的进程是否仍在运行?
您不必确定这一点,因为在关闭与文件关联的文件描述符后,即使进程已终止,植入锁也会自动释放。
如何使其他用户可以删除锁定文件,如果不使用?
如果您要锁定设备文件本身,则不需要删除文件。 即使你决定在/var/lock
锁定一个普通的文件,你也不需要删除这个文件来释放这个锁。
Hasturkun的回答是让我走上正轨的那个人。
这是我使用的代码
#include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <fcntl.h> /*! Try to get lock. Return its file descriptor or -1 if failed. * * @param lockName Name of file used as lock (ie '/var/lock/myLock'). * @return File descriptor of lock file, or -1 if failed. */ int tryGetLock( char const *lockName ) { mode_t m = umask( 0 ); int fd = open( lockName, O_RDWR|O_CREAT, 0666 ); umask( m ); if( fd >= 0 && flock( fd, LOCK_EX | LOCK_NB ) < 0 ) { close( fd ); fd = -1; } return fd; } /*! Release the lock obtained with tryGetLock( lockName ). * * @param fd File descriptor of lock returned by tryGetLock( lockName ). * @param lockName Name of file used as lock (ie '/var/lock/myLock'). */ void releaseLock( int fd, char const *lockName ) { if( fd < 0 ) return; remove( lockName ); close( fd ); }
我正在使用chmike发布的代码,并注意到一个小缺陷。 在打开的锁定文件中,我遇到了一个问题。 有时,多个线程同时打开锁定文件。
所以我删除了“remove(lockName);” 从“releaseLock()”函数行。 我不明白为什么,但不知怎的,这个行动帮助了这个情况。
我一直在使用下面的代码来测试锁定文件。 通过它的输出,可以看到几个线程同时开始使用一个锁。
void testlock(void) { # pragma omp parallel num_threads(160) { int fd = -1; char ln[] = "testlock.lock"; while (fd == -1) fd = tryGetLock(ln); cout << omp_get_thread_num() << ": got the lock!"; cout << omp_get_thread_num() << ": removing the lock"; releaseLock(fd,ln); } }
扩展Hasturhun的答案。 不使用锁文件的存在或不存在作为指示器,如果不存在,则需要创建锁文件,然后获得文件的排他锁。
这种方法的优点是不像许多其他同步程序的方法,操作系统应该为你清理,如果你的程序退出没有解锁。
所以程序结构是这样的:
1: open the lock file creating it if it doesn't exist 2: ask for an exclusive lock an agreed byte range in the lock file 3: when the lock is granted then 4: <do my processing here> 5: release my lock 6: close the lock file end
在步骤:您可以阻止等待授予锁或立即返回。 您锁定的字节实际上不必在文件中存在。 如果你能得到Marc J. Rochkind的高级Unix编程的副本,他将开发一个完整的C库,使用这种方法来提供一种同步程序的方法,然后由OS来整理程序,但程序将退出。