进程锁,采用常见的文件锁,当时在OSX平台下也鼓捣了不短时间,所以记录下: 入口类, creator: /// <summary> /// lock a file, and handle this file until release lock,\n /// it is a writeStrem in win , a fcntl lock in unix.\n /// remember to release or dispose when no reference. \n /// <b>warnning: in unix, file lock can only check the lock between diffrent process, /// use System.Threading.Mutex instead</b> /// </summary> public class FileLockHandler : System.IDisposable { private string lockfilepath = string.Empty; protected FileLockHandler() { } public string CurrLockFilePath { get { return lockfilepath; } } /// <summary> /// create a filelock handle, should be dispose after no reference /// </summary> public static FileLockHandler Create() { if (MonoDevelop.Core.Platform.IsWindows) return new WinFileLockHandler(); else return new UnixFileLockHandler(); } /// <summary> /// lock a filepath as a write handle in unix or win, return false when lock failed\n /// @PathTooLongException filepath is too long (maybe>248 on win)\n /// @UnauthorizedAccessException access failed\n /// @SecurityException access failed\n /// </summary> /// <param name="filepath"></param> /// <returns></returns> public bool LockFile(string filepath) { bool islocksuccess = OnLockFile(filepath); lockfilepath = filepath; return islocksuccess; } protected virtual bool OnLockFile(string filepath) { return false; } /// <summary> /// check filepath is locked as a write handle in unix or win, return false when lock failed\n /// returns true when filepath is locked or <b>filepath cannot access</b> /// @FileNotFoundException filepath not exists /// @PathTooLongException filepath is too long (maybe>248 on win) /// @UnauthorizedAccessException access failed /// @SecurityException access failed /// </summary> /// <param name="filepath"></param> /// <returns></returns> public bool IsFileLocked(string filePath) { bool isExists = File.Exists(filePath); bool isLocked = isExists; if (!isExists) return false; else { isLocked = OnIsFileLocked(filePath); } return isLocked; } protected virtual bool OnIsFileLocked(string filePath) { return false; } public void ReleaseLock() { if (!File.Exists(lockfilepath)) throw new FileNotFoundException("Locked File in Handler Not Found: ", lockfilepath); OnReleaseLock(); File.Delete(lockfilepath); lockfilepath = string.Empty; } protected virtual void OnReleaseLock() { } /// <summary> /// make some long length string path to a short string name /// (we can not create file which path is too long maybe>248) /// check file name and ensure the return 32 chexadecimal string. /// </summary> public static string GetMD5String(string filepath) { filepath = System.IO.Path.Combine(filepath); // Create a new instance of the MD5CryptoServiceProvider object. var md5Hasher = System.Security.Cryptography.MD5.Create(); // Convert the input string to a byte array and compute the hash. byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(filepath)); // Create a new Stringbuilder to collect the bytes // and create a string. StringBuilder sBuilder = new StringBuilder(); // Loop through each byte of the hashed data // and format each one as a hexadecimal string. for (int i = 0; i < data.Length; i++) { sBuilder.Append(data[i].ToString("x2")); } // Return the hexadecimal string. return sBuilder.ToString(); } public void Dispose() { try { ReleaseLock(); } catch(System.Exception) { } } } win 平台,比较容易理解 class WinFileLockHandler : FileLockHandler { private FileStream lockwritehandle = null; public WinFileLockHandler() : base() { } protected override bool OnLockFile(string filePath) { try { lockwritehandle = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); } catch (System.Exception ex) { throw new System.Exception("can not lock file: ", ex); } return true; } protected override bool OnIsFileLocked(string filePath) { bool isLocked = false; try { using (var templock = new FileStream(filePath, FileMode.Open, FileAccess.Write, FileShare.None)) { isLocked = false; templock.Close(); } } catch (System.IO.IOException) { isLocked = true; } catch(System.Exception ex) { throw new System.Exception("can not be a lock file:", ex); } return isLocked; } protected override void OnReleaseLock() { using (lockwritehandle) { if (lockwritehandle != null) { lockwritehandle.Close(); lockwritehandle.Dispose(); } else throw new FileNotFoundException("no lock to release"); } } } Unix 平台,原理为使用 fcntl 操作和读取文件状态, 当软件 dump 的时候,锁文件不会自动销毁,所以如果考虑比较全的话,应该有个清理不在正在使用的锁文件。 class UnixFileLockHandler : FileLockHandler { private Flock flockhandle; private int flockfd = 0; public UnixFileLockHandler() : base() { flockhandle.l_len = 0; flockhandle.l_pid = Syscall.getpid(); flockhandle.l_start = 0; flockhandle.l_type = LockType.F_WRLCK; flockhandle.l_whence = SeekFlags.SEEK_SET; } protected override bool OnLockFile(string filepath) { bool isLocked = false; flockhandle.l_type = LockType.F_WRLCK; flockfd = Syscall.open(filepath, OpenFlags.O_CREAT | OpenFlags.O_RDWR, FilePermissions.DEFFILEMODE); int ret = Syscall.fcntl(flockfd, FcntlCommand.F_SETLK, ref flockhandle); if (ret != -1) isLocked = true; else throw new System.InvalidOperationException(filepath + "has already been locked!"); return isLocked; } protected override bool OnIsFileLocked(string filePath) { bool isLocked = true; if (filePath == CurrLockFilePath) //because file lock can not work in the same process(please use mutex instead), return isLocked; flockhandle.l_type = LockType.F_WRLCK; int tmpfilehd = Syscall.open(filePath, OpenFlags.O_RDWR, FilePermissions.DEFFILEMODE); int ret = Syscall.fcntl(tmpfilehd, FcntlCommand.F_SETLK, ref flockhandle); if (ret != -1) isLocked = false; flockhandle.l_type = LockType.F_UNLCK; Syscall.fcntl(tmpfilehd, FcntlCommand.F_SETLK, ref flockhandle); return isLocked; } protected override void OnReleaseLock() { flockhandle.l_type = LockType.F_UNLCK; int ret = Syscall.fcntl(flockfd, FcntlCommand.F_SETLK, ref flockhandle); if (ret == -1) { throw new System.InvalidOperationException("Release Lock File failed: " + CurrLockFilePath); } Syscall.close(flockfd); } } Previous matrix 中提取旋转、位移、缩放分量 Next 选择一个合适的 AR SDK FEATURED TAGS Unity FRIENDS