I’m learning file link count. Only when link count reaches 0 can file’s contents be deleted. In my test the process opens a file in directory “/home/hel/myfile” and sleep 10(s). At the same time I delete it using “rm /home/hel/myfile”. Then I use command “ls” and display No such file. But in fact, the file still exists because the fd hasn’t been closed. If so, “ls” can’t show whether a file really exist. I’m confused about “ls”. Or how can I judge a file really exists?
#include <fcntl.h> #include <stdlib.h> int main(void) { int fd; fd = open("/home/hel/myfile", O_RDWR); if (fd < 0) { exit(-1); } sleep(10); // sleep 10(s) close(fd); return 0; }
Advertisement
Answer
A filename is like a label pointing to the real data. The real data is stored in an inode. An inode normally has just one filename pointing to it, a link count of one. But it can have more than one.
Here’s a visual example. When you create a normal file it puts your data in a new inode and points the filename at it.
$ echo "foo" > some/file "some/file" -> [data: "foo", links: 1]
When you make another file, the same thing happens.
$ echo "bar" > another/file "some/file" -> [data: "foo", links: 1] "another/file" -> [data: "bar", links: 1]
But if you make a hard link, now the inode has two links.
$ ln some/file some/link "some/file" -> [data: "foo", links: 2] ^ "some/link" -----/ "another/file" -> [data: "bar", links: 1]
In fact, normal files are hard links. There’s nothing to distinguish some/file
from some/link
except the filename. Neither one is the “real” file, they’re both links.
If a link is deleted, the link count is decremented. This is why in some languages you call unlink
to delete a file.
$ rm some/file "some/link" -> [data: "foo", links: 1] "another/file" -> [data: "bar", links: 1]
When it reaches 0, the inode is available to be overwritten. The data is still there, but there’s nothing pointing to it. This is why you can sometimes recover deleted files.
$ rm some/link [data: "foo", links: 0] "another/file" -> [data: "bar", links: 1]
What about file handles? They don’t change the link count. Instead, on Unix (not Windows), the operating system keeps track of how many open handles there are to a given inode. So long as there is an open handle it will not allow the inode to be overwritten.
fd = open("another/file", O_RDWR); [data: "foo", links: 0] fd --- / "another/file" -> [data: "bar", links: 1] $ rm another/file [data: "foo", links: 0] fd -> [data: "bar", links: 0] close(fd); [data: "foo", links: 0] [data: "bar", links: 0]
This lets you do things like create a temp file, open a handle to both read and write to it, and immediately delete it. The program can then continue to read and write to temporary disk storage, but nobody can see the file.