uso - linux numero inodo
¿Qué es un inodo anónimo en Linux? (2)
Hice una búsqueda en Google sobre "inodo anónimo" y parece que está relacionado con epoll ... pero, ¿qué es realmente?
Al menos en algunos contextos, un inodo anónimo es un inodo sin una entrada de directorio adjunta. La forma más fácil de crear tal inodo es como tal:
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
con O_TMPFILE
Esta sería una buena definición de inodo anónimo: crea un inodo dentro de un directorio dado sin ningún nombre, que no aparece en absoluto con ls
.
Luego, cuando cierras el descriptor, el archivo se borra.
Fue agregado en 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;
}
Probado en Ubuntu 17.04, Linux 4.10, glibc 2.24, se ejecuta con:
gcc -o a.out -std=c99 -Wall -Wextra a.c
./a.out
anon_inode_getfd
función del kernel de Linux
Si está tratando con módulos del kernel, esta es una definición probable.
Lo llamas como
fd = anon_inode_getfd("random", &fops_anon, NULL, O_RDONLY | O_CLOEXEC);
y devuelva fd
al usuario, por ejemplo, desde un ioctl
.
Ahora el usuario tiene un fd
con file_operations
e inode
arbitrarias asociadas, y cuando ese fd
se cierra, todo se libera.
Este método es útil, por ejemplo, si desea tener múltiples syscalls de read
, pero no quiere crear múltiples archivos de dispositivo, que más contaminan /dev
: simplemente crea ioctl
extra en su lugar.
Ejemplo ejecutable mínimo con 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)