Was ist eine anonyme Inode in Linux?
Frage
Ich habe eine Google-Suche über „anonymous inode“ und es scheint es epoll verwandt ist ... aber was ist es eigentlich?
Lösung
Zumindest in manchen Kontexten ein anonymer Inode ist eine Inode ohne angeschlossenen Verzeichniseintrag. Der einfachste Weg, eine solche Inode zu schaffen, ist als solche:
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.
Andere Tipps
open
mit O_TMPFILE
Dies wäre eine gute Definition von anonymen Inode sein. Es schafft eine Inode in einem bestimmten Verzeichnis ohne Namen, die überhaupt nicht mit ls
erscheinen
Wenn Sie dann den Deskriptor schließen die Datei gelöscht wird.
Es wurde in Linux 3.11 hinzugefügt.
#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;
}
Getestet in Ubuntu 17.04, Linux 4.10, glibc 2.24, führen Sie mit:
gcc -o a.out -std=c99 -Wall -Wextra a.c
./a.out
anon_inode_getfd
Linux-Kernel-Funktion
Wenn Sie mit Kernel-Module handelt, ist dies eine wahrscheinliche Definition.
Sie nennen es wie:
fd = anon_inode_getfd("random", &fops_anon, NULL, O_RDONLY | O_CLOEXEC);
und Rückkehr fd
an Benutzer, beispielsweise von einem ioctl
.
Jetzt hat der Benutzer eine fd
mit zugehörigen beliebigen file_operations
und inode
, und wenn das fd
geschlossen ist, wird alles befreit.
Dieses Verfahren ist nützlich, zum Beispiel wenn Sie mehrere read
syscalls haben wollen, aber nicht wollen, mehrere Gerätedateien zu erzeugen, die weiter verunreinigt /dev
: Sie nur zusätzliche ioctl
s erstellen, anstatt
Minimal runnable Beispiel mit QEMU Buildroot:
- https://github.com/ cirosantilli / linux-Kernel-Modul-Cheat / Blob / de6c179fc0cf122789f0fe85cc69b847a1f4fe9c / kernel_module / anonymous_inode.c
- https://github.com/ cirosantilli / linux-Kernel-Modul-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)