如何知道文件是否正在被复制?
我目前正在尝试检查文件从一个目录到另一个目录的复制是否完成。 我想知道目标文件是否仍在复制。
所以我想获取此文件上打开的文件描述符的数量。 我使用 C 语言,但没有真正找到解决该问题的方法。
I am currently trying to check wether the copy of a file from a directory to another is done.
I would like to know if the target file is still being copied.
So I would like to get the number of file descriptors openned on this file.
I use C langage and don't really find a way to resolve that problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
如果您能够打开文件进行写入,则操作系统很可能已完成复制并释放了其锁定。然而,不同的操作系统对此的行为可能有所不同。
另一种方法是打开源文件和目标文件进行读取并比较它们的大小。如果它们大小相同,则副本很可能已完成。您可以使用
fseek()
和ftell()
来确定 C 中文件的大小:If you're able to open the file for writing, there's a good chance that the OS has finished the copy and has released its lock on it. Different operating systems may behave differently for this, however.
Another approach is to open both the source and destination files for reading and compare their sizes. If they're of identical size, the copy has very likely finished. You can use
fseek()
andftell()
to determine the size of a file in C:在 Linux 中,尝试使用 lsof 命令,该命令会列出系统上所有打开的文件。
编辑1:唯一想到的C语言功能是fstat函数。您可以将其与结构体的
st_mtime
(上次修改时间)字段一起使用 - 一旦该值停止更改(例如 10 秒的时间),那么您可以假设文件复制操作已经停止了。编辑2:另外,在Linux上,您可以遍历 /proc/[pid]/fd查看哪些文件已打开。里面的文件有符号链接,但是C的
readlink()
函数可以告诉你它的路径,这样你就可以看到它是否仍然打开。使用 getpid(),您将知道程序的进程 ID(如果您正在程序内进行文件复制),从而知道在 /proc 中查找何处。In linux, try the
lsof
command, which lists all of the open files on your system.edit 1: The only C language feature that comes to mind is the fstat function. You might be able to use that with the struct's
st_mtime
(last modification time) field - once that value stops changing (for, say, a period of 10 seconds), then you could assume that file copy operation has stopped.edit 2: also, on linux, you could traverse /proc/[pid]/fd to see which files are open. The files in there are symlinks, but C's
readlink()
function could tell you its path, so you could see whether it is still open. Usinggetpid()
, you would know the process ID of your program (if you are doing a file copy from within your program) to know where to look in /proc.我认为您的基本错误是尝试将 C 程序与不用于同步的 shell 工具/外部程序同步。如果您对执行复制的程序/脚本有一定程度的控制,则应该修改它以对目标文件执行某种类型的建议锁定(最好是基于 fcntl 的)。然后你的其他程序可以简单地阻止获取锁。
如果您对执行复制的程序没有任何控制权,唯一的解决方案取决于不可移植的 hack,例如 lsof 或 Linux inotify API。
I think your basic mistake is trying to synchronize a C program with a shell tool/external program that's not intended for synchronization. If you have some degree of control over the program/script doing the copying, you should modify it to perform advisory locking of some sort (preferably
fcntl
-based) on the target file. Then your other program can simply block on acquiring the lock.If you don't have any control over the program performing the copy, the only solutions depend on non-portable hacks like
lsof
or Linuxinotify
API.(这个答案做出了一个很大很大的假设,即这将在 Linux 上运行。)
lsof 的 C 源代码是一个工具,它告诉哪些程序当前拥有特定文件的打开文件描述符。 免费提供。然而,只是警告你,我无法理解它的任何意义。有提到读取内核内存,所以对我来说,这要么是巫术,要么是黑魔法。
也就是说,没有什么可以阻止您通过自己的程序运行 lsof。从您自己的程序运行第三方程序通常是您出于多种原因而试图避免的事情,例如安全性(如果流氓用户将
lsof
更改为恶意程序,它将以您的程序的权限运行,潜在的灾难性后果),但是检查lsof
源代码,我得出的结论是没有公共API来确定哪个程序打开了哪个文件。如果您不害怕人们更改/usr/sbin
中的程序,您可以考虑这样做。如果您还需要知道哪个程序打开了您的文件(大概是
cp
?),您可以使用popen
读取lsof
的输出类似的时尚。popen
描述符的行为类似于fopen
描述符,因此您所需要做的就是fread
它们并查看是否可以找到程序的名称。在我的机器上,lsof
输出如下所示:(This answer makes the big, big assumption that this will be running on Linux.)
The C source code of
lsof
, a tool that tells which programs currently have an open file descriptor to a specific file, is freely available. However, just to warn you, I couldn't make any sense out of it. There are references to reading kernel memory, so to me it's either voodoo or black magic.That said, nothing prevents you from running
lsof
through your own program. Running third-party programs from your own program is normally something you try to avoid for several reasons, like security (if a rogue user changeslsof
for a malicious program, it will run with your program's privileges, with potentially catastrophic consequences) but inspecting thelsof
source code, I came to the conclusion that there's no public API to determine which program has which file open. If you're not afraid of people changing programs in/usr/sbin
, you might consider this.If you also need to know which program has your file open (presumably
cp
?), you can usepopen
to read the output oflsof
in a similar fashion.popen
descriptors behave likefopen
descriptors, so all you need to do isfread
them and see if you can find your program's name. On my machine,lsof
output looks like this:正如 poundifdef 提到的,fstat() 函数可以为您提供当前的修改时间。但 fstat 还可以提供文件的大小。
回到 C 的昏暗黑暗时代,当我监视由各种程序复制的文件时,我无法控制我总是:
如果您不知道目标文件是什么,那么您唯一真正的选择是#2,但使用较大的 N 以允许最坏情况下的网络和本地 CPU 延迟,同时具有良好的安全系数。
As poundifdef mentioned, the fstat() function can give you the current modification time. But fstat also gives you the size of the file.
Back in the dim dark ages of C when I was monitoring files being copied by various programs I had no control over I always:
If you don't know what the target file is then the only real choice you have is #2, but user a larger N to allow for the worse case network and local CPU delays, with a healthy safety factor.
使用 boost libs 将解决该问题
using boost libs will solve the issue
如果您可以控制它,我建议在执行复制的程序上使用复制移动习惯用法:
mv
只是更改一些文件系统条目,并且是原子的且速度非常快与副本相比。If you have control of it, I would recommend using the copy-move idiom on the program doing the copying:
The
mv
just changes some filesystem entries and is atomic and very fast compared to the copy.