我在谷歌上搜索了“匿名inode”,似乎它与epoll有关......但它实际上是什么?
2 回答
至少在某些情况下,匿名 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.
open
和O_TMPFILE
这将是匿名 inode 的一个很好的定义:它在给定目录中创建一个没有任何名称的 inode,它根本不会出现在ls
.
然后,当您关闭描述符时,文件将被删除。
它是在 Linux 3.11 中添加的。
主程序
#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;
}
编译并运行:
gcc -o main.out -std=c99 -Wall -Wextra -pedantic main.c
./main.out
因此,这本质上是实现临时文件的最佳方式:如何在 C++ 中创建临时文本文件?因为它可以:
- 总是立即找到一个免费的名称,而无需我们遍历文件名(不需要名称!)
- 并自动删除
将其与更手动的目录方法进行比较,如下所示:如何在 C++ 中创建临时目录?
在 Ubuntu 17.04、Linux 4.10、glibc 2.24 中测试。
里面O_TMPFILE
的样子/proc/PID/fd
我们可以通过以下方式快速检查它:
#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();
}
然后是示例输出:
pid 15952
inode 44698689
我们的确是:
ls -l /proc/15952/fd
其中包含:
3 -> '/home/ciro/test/#44698689 (deleted)'
它向我们展示了如何为给定进程查找临时文件并查看它们inode
和 inode 父目录。
anon_inode_getfd
Linux内核函数
如果您正在处理内核模块,这可能是一个定义。
你这样称呼它:
fd = anon_inode_getfd("random", &fops_anon, NULL, O_RDONLY | O_CLOEXEC);
并返回fd
给用户,例如从ioctl
.
现在用户有一个fd
关联的任意file_operations
and inode
,当它fd
关闭时,一切都被释放。
此方法很有用,例如,如果您想拥有多个read
系统调用,但又不想创建多个设备文件,这会进一步污染/dev
:您只需创建额外ioctl
的 s。
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
#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
在 /proc/PID/fd
这些是管道和套接字,请参阅:https ://unix.stackexchange.com/questions/463548/what-is-anon-inode-in-the-output-of-ls-l