什么是 Linux 中的匿名 inode?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4508998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is an anonymous inode in Linux?
提问by mrkschan
I made a google search about "anonymous inode" and it seems it's related to epoll ... but what actually is it?
我在谷歌上搜索了“匿名 inode”,它似乎与 epoll 相关……但它究竟是什么?
采纳答案by mrkschan
At least in some contexts, an anonymous inode is an inode without an attached directory entry. The easiest way to create such an inode is as such:
至少在某些上下文中,匿名 inode 是没有附加目录条目的 inode。创建此类 inode 的最简单方法如下:
int fd = open( "/tmp/file", O_CREAT | O_RDWR, 0666 );
unlink( "/tmp/file" );
// Note that the descriptor fd now points to an inode that has no filesystem entry; you
// can still write to it, fstat() it, etc. but you can't find it in the filesystem.
回答by Ciro
open
with O_TMPFILE
open
和 O_TMPFILE
This would be a good definition of anonymous inode: it creates an inode inside a given directory without any name, which does not appear at all with ls
.
这将是匿名 inode 的一个很好的定义:它在给定的目录中创建一个没有任何名称的 inode,它根本不会出现在ls
.
Then when you close the descriptor the file is deleted.
然后,当您关闭描述符时,文件将被删除。
It was added in Linux 3.11.
它是在 Linux 3.11 中添加的。
main.c
主文件
#define _GNU_SOURCE
#include <assert.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
char buf[] = { 'a', 'b', 'c', 'd' };
char buf2[] = { 'e', 'f', 'g', 'h' };
int f, ret;
size_t off;
/* write */
f = open(".", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
ret = write(f, buf, sizeof(buf));
/* Interactivelly check if anything changed on directory. It hasn't. */
/*puts("hit enter to continue");*/
/*getchar();*/
/* read */
lseek(f, 0, SEEK_SET);
off = 0;
while ((ret = read(f, buf2 + off, sizeof(buf) - off))) {
off += ret;
}
close(f);
assert(!memcmp(buf, buf2, sizeof(buf)));
return EXIT_SUCCESS;
}
Compile and run:
编译并运行:
gcc -o main.out -std=c99 -Wall -Wextra -pedantic main.c
./main.out
This is therefore essentially the optimal way of implementing temporary files: How to create a temporary text file in C++?as it can:
因此,这本质上是实现临时文件的最佳方式:如何在 C++ 中创建临时文本文件?因为它可以:
- always immediately find a free name without us having to loop over filenames (no name is needed!)
- and has automatic deletion
- 总是立即找到一个免费名称,而无需我们遍历文件名(不需要名称!)
- 并有自动删除
Compare that to a more manual method for directories as the one shown at: How to create a temporary directory in C++?
将其与更手动的目录方法进行比较,如以下所示:如何在 C++ 中创建临时目录?
Tested in Ubuntu 17.04, Linux 4.10, glibc 2.24.
在 Ubuntu 17.04、Linux 4.10、glibc 2.24 中测试。
How O_TMPFILE
looks like in /proc/PID/fd
O_TMPFILE
看起来如何/proc/PID/fd
We can examine it quickly with:
我们可以通过以下方式快速检查它:
#define _GNU_SOURCE
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
int f = open(".", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
struct stat s;
fstat(f, &s);
printf("pid %jd\n", (intmax_t)getpid());
printf("inode %jd\n", (intmax_t)s.st_ino);
getchar();
}
then for a sample output:
然后对于示例输出:
pid 15952
inode 44698689
we do:
我们的确是:
ls -l /proc/15952/fd
and that contains:
其中包含:
3 -> '/home/ciro/test/#44698689 (deleted)'
which shows us how to find temporary files for a given process and see their inode
and inode parent directory.
它向我们展示了如何为给定进程查找临时文件并查看它们inode
和 inode 父目录。
anon_inode_getfd
Linux kernel function
anon_inode_getfd
Linux内核函数
If you are dealing with kernel modules, this is a likely definition.
如果您正在处理内核模块,这可能是一个定义。
You call it like:
你这样称呼它:
fd = anon_inode_getfd("random", &fops_anon, NULL, O_RDONLY | O_CLOEXEC);
and return fd
to user, e.g. from an ioctl
.
并返回fd
给用户,例如从ioctl
.
Now the user has an fd
with associated arbitrary file_operations
and inode
, and when that fd
is closed, everything is freed.
现在用户有一个fd
关联的任意file_operations
and inode
,当它fd
关闭时,一切都被释放。
This method is useful e.g. if you want to have multiple read
syscalls, but don't want to create multiple device files, which further pollutes /dev
: you just create extra ioctl
s instead.
这种方法很有用,例如,如果您想要多个read
系统调用,但不想创建多个设备文件,这会进一步污染/dev
:您只需创建额外的ioctl
s。
Minimal runnable example with QEMU Buildroot:
使用 QEMU Buildroot 的最小可运行示例:
- https://github.com/cirosantilli/linux-kernel-module-cheat/blob/de6c179fc0cf122789f0fe85cc69b847a1f4fe9c/kernel_module/anonymous_inode.c
- https://github.com/cirosantilli/linux-kernel-module-cheat/blob/de6c179fc0cf122789f0fe85cc69b847a1f4fe9c/rootfs_overlay/anonymous_inode.sh
- https://github.com/cirosantilli/linux-kernel-module-cheat/blob/de6c179fc0cf122789f0fe85cc69b847a1f4fe9c/kernel_module/anonymous_inode.c
- https://github.com/cirosantilli/linux-kernel-module-cheat/blob/de6c179fc0cf122789f0fe85cc69b847a1f4fe9c/rootfs_overlay/anonymous_inode.sh
#include <asm/uaccess.h> /* copy_from_user, copy_to_user */
#include <linux/anon_inodes.h>
#include <linux/debugfs.h>
#include <linux/errno.h> /* EFAULT */
#include <linux/fs.h>
#include <linux/jiffies.h>
#include <linux/kernel.h> /* min */
#include <linux/module.h>
#include <linux/printk.h> /* printk */
#include "anonymous_inode.h"
MODULE_LICENSE("GPL");
static struct dentry *dir;
static ssize_t read(struct file *filp, char __user *buf, size_t len, loff_t *off)
{
char kbuf[1024];
size_t ret;
ret = snprintf(kbuf, sizeof(kbuf), "%llu", (unsigned long long)jiffies);
if (copy_to_user(buf, kbuf, ret)) {
ret = -EFAULT;
}
return ret;
}
static const struct file_operations fops_anon = {
.read = read,
};
static long unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long argp)
{
int fd;
switch (cmd) {
case LKMC_ANONYMOUS_INODE_GET_FD:
fd = anon_inode_getfd(
"random",
&fops_anon,
NULL,
O_RDONLY | O_CLOEXEC
);
if (copy_to_user((void __user *)argp, &fd, sizeof(fd))) {
return -EFAULT;
}
break;
default:
return -EINVAL;
break;
}
return 0;
}
static const struct file_operations fops_ioctl = {
.owner = THIS_MODULE,
.unlocked_ioctl = unlocked_ioctl
};
static int myinit(void)
{
dir = debugfs_create_dir("lkmc_anonymous_inode", 0);
debugfs_create_file("f", 0, dir, NULL, &fops_ioctl);
return 0;
}
static void myexit(void)
{
debugfs_remove_recursive(dir);
}
module_init(myinit)
module_exit(myexit)
anon_inode
in /proc/PID/fd
anon_inode
在 /proc/PID/fd
These are pipes and sockets, see: https://unix.stackexchange.com/questions/463548/what-is-anon-inode-in-the-output-of-ls-l
这些是管道和套接字,请参阅:https: //unix.stackexchange.com/questions/463548/what-is-anon-inode-in-the-output-of-ls-l