我有以下问题。我想创建一个基于文件系统的会话存储,其中每个会话数据都存储在以会话 ID 命名的简单文件中。

我想要以下 API: write(sid,data,timeout), read(sid,data,timeout), remove(sid)其中 sid== 文件名,另外我想要某种可以删除所有超时会话的 GC。

如果您使用单个进程,这是相当简单的任务,但如果您使用多个进程,甚至通过 NFS,则绝对不是微不足道的任务。

我想到的最简单的解决方案是:

write/read:
   fd=open(file_name,O_CREAT | O_RDWR); // create a new file or use exsting
   fcntl_lock_file(fd)
   save data to fd/read data from fd
   fcntl_unlock_file(fd)
   close(fd)

GC:
   fd=open(file_name,O_RDWR);
   fcntl_lock_file(fd)
   if(timed_out)
      unlink(file_name)
   fcntl_unlock_file(fd)
   close(fd)

文件名称和文件锁在文件描述符上工作的最大问题。所以上面的方法在以下情况下不起作用:

GC - open,
write - open
GC - lock, unlink, unlock, close // file still exists because held by write
write - lock, write, unlock, close // file removed

有人知道如何解决这样的问题吗?是否有任何技巧可以将文件锁定和文件删除或在文件原子上进行操作?

笔记:

  • 我不想使用数据库,
  • 我正在寻找 Unix 的解决方案
  • 解决方案应适用于标准 POSIX 调用,例如 fcnl、open、close、unlink

谢谢。

澄清 主要问题是对文件的操作(名称——取消链接)应该通过文件描述符的操作——锁定来原子地完成:

  • 打开、取消链接——处理文件
  • fnctl——处理描述符
有帮助吗?

解决方案

这不行吗?

write/read:
   fd=open(file_name,O_CREAT | O_RDWR); // create a new file or use exsting
   fcntl_lock_file(fd)
   if stat(file_name).{st_dev, st_ino} != fstat(fd).{st_dev, st_ino}
       unlock, close, retry
   save data to fd/read data from fd
   fcntl_unlock_file(fd)
   close(fd)

如果 stat 失败并显示 EEXIST(文件名不存在)或显示当前文件与您打开的文件不同,bail。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top