什么是 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 00:48:30  来源:igfitidea点击:

What is an anonymous inode in Linux?

linuxepollinode

提问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

openwith O_TMPFILE

openO_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;
}

GitHub upstream.

GitHub 上游.

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_TMPFILElooks 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 inodeand inode parent directory.

它向我们展示了如何为给定进程查找临时文件并查看它们inode和 inode 父目录。

anon_inode_getfdLinux kernel function

anon_inode_getfdLinux内核函数

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 fdto user, e.g. from an ioctl.

并返回fd给用户,例如从ioctl.

Now the user has an fdwith associated arbitrary file_operationsand inode, and when that fdis closed, everything is freed.

现在用户有一个fd关联的任意file_operationsand inode,当它fd关闭时,一切都被释放。

This method is useful e.g. if you want to have multiple readsyscalls, but don't want to create multiple device files, which further pollutes /dev: you just create extra ioctls instead.

这种方法很有用,例如,如果您想要多个read系统调用,但不想创建多个设备文件,这会进一步污染/dev:您只需创建额外的ioctls。

Minimal runnable example with QEMU Buildroot:

使用 QEMU Buildroot 的最小可运行示例:

#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_inodein /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