Optimal lock file method
Take a look at the enlightening presentation File Locking Tricks and Traps:
This short talk presents several common pitfalls of file locking and a few useful tricks for using file locking more effectively.
Edit: To address your questions more precisely:
Is there a better synchronization method than the lock file?
As @Hasturkun already mentioned and as the presentation above told, the system call you need to use is flock(2)
. If the resource you'd like to share across many users is already file-based (in your case it is /dev/ttyUSBx
), then you can flock
the device file itself.
How to determine if the process who created the lock file is still running?
You don't have to determine this, as the flock
-ed lock will be automatically released upon closing the file descriptor associated with your file, even if the process was terminated.
How making it possible for another user to remove the lock file if not in use?
If you would lock the device file itself, then there will be no need to remove the file. Even if you would decide to lock an ordinary file in /var/lock
, with flock
you will not need to remove the file in order to release the lock.
You should probably be using flock()
, as in
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
}
The answer of Hasturkun is the one that has put me on track.
Here is the code I use
#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 (i.e. '/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 (i.e. '/var/lock/myLock').
*/
void releaseLock( int fd, char const *lockName )
{
if( fd < 0 )
return;
remove( lockName );
close( fd );
}