Windows平台下lockf()有无替代实现?如何移植对应Linux代码?
Windows平台
lockf()函数替代实现与代码移植方案 核心替代逻辑
Windows原生没有POSIX标准的lockf()实现,你代码中用到的lockf(fd, F_LOCK, 0)是阻塞式独占整个文件锁,对应可以使用Win32 API的LockFileEx实现完全对齐的行为。
移植注意事项
- Windows下POSIX兼容函数的名称前缀为下划线,比如
open对应_open、lseek对应_lseek、close对应_close - 从C runtime的文件描述符获取Win32原生文件句柄,使用
_get_osfhandle()函数 LockFileEx默认自动随文件句柄关闭释放锁,和lockf行为一致,无需额外调用解锁接口
适配后的跨平台代码
#include <windows.h> #include <errno.h> // 其他原有头文件保持不变 static string load_bulletin_from_file(const char* cache_filename) { #ifdef _WIN32 int fd = _open(cache_filename, _O_RDWR); #else int fd = open(cache_filename, O_RDWR); // lockf requires O_RDWR #endif if (fd == -1) { etiLog.level(error) << "TAI-UTC bulletin open cache for reading: " << strerror(errno); return ""; } #ifdef _WIN32 _lseek(fd, 0, SEEK_SET); #else lseek(fd, 0, SEEK_SET); #endif vector<char> buf(1024); vector<char> new_bulletin_data; bool lock_success = false; #ifdef _WIN32 HANDLE hFile = (HANDLE)_get_osfhandle(fd); if (hFile != INVALID_HANDLE_VALUE) { OVERLAPPED ov = {0}; // 阻塞式独占整个文件锁,和F_LOCK行为完全一致 if (LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK, 0, MAXDWORD, MAXDWORD, &ov)) { lock_success = true; } else { // 把Win32错误转成errno方便统一日志 errno = EACCES; } } #else ssize_t ret = lockf(fd, F_LOCK, 0); if (ret == 0) { lock_success = true; } #endif if (lock_success) { // exclusive lock acquired ssize_t ret; do { #ifdef _WIN32 ret = _read(fd, buf.data(), buf.size()); #else ret = read(fd, buf.data(), buf.size()); #endif if (ret == -1) { #ifdef _WIN32 _close(fd); #else close(fd); #endif etiLog.level(error) << "TAI-UTC bulletin read cache: " << strerror(errno); return ""; } copy(buf.data(), buf.data() + ret, back_inserter(new_bulletin_data)); } while (ret > 0); #ifdef _WIN32 _close(fd); #else close(fd); #endif return string{new_bulletin_data.data(), new_bulletin_data.size()}; } else { etiLog.level(error) << "TAI-UTC bulletin acquire cache lock for reading: " << strerror(errno); #ifdef _WIN32 _close(fd); #else close(fd); #endif } return ""; }
可选兼容方案
如果你的项目需要更精简的跨平台封装,也可以自己封装一个跨平台的lockf兼容函数,把Windows和POSIX的逻辑隐藏在函数内部,业务代码不需要做大量修改。
内容的提问来源于stack exchange,提问作者Hojzerice
相关产品推荐
相关产品推荐

