open
con O_TMPFILE
Esta sería una buena definición de inodo anónimo:crea un inodo dentro de un directorio determinado sin ningún nombre, que no aparece en absoluto con ls
.
Luego, cuando cierra el descriptor, el archivo se elimina.
Se agregó en Linux 3.11.
principal.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 ascendente.
Compilar y ejecutar:
gcc -o main.out -std=c99 -Wall -Wextra -pedantic main.c
./main.out
Por lo tanto, esta es esencialmente la forma óptima de implementar archivos temporales:¿Cómo crear un archivo de texto temporal en C++? como puede:
- siempre encuentre inmediatamente un nombre libre sin que tengamos que repetir los nombres de los archivos (¡no se necesita ningún nombre!)
- y tiene eliminación automática
Compare eso con un método más manual para directorios como el que se muestra en:¿Cómo crear un directorio temporal en C++?
Probado en Ubuntu 17.04, Linux 4.10, glibc 2.24.
Cómo O_TMPFILE
parece en /proc/PID/fd
Podemos examinarlo rápidamente con:
#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();
}
luego para una salida de muestra:
pid 15952
inode 44698689
hacemos:
ls -l /proc/15952/fd
y que contiene:
3 -> '/home/ciro/test/#44698689 (deleted)'
que nos muestra cómo encontrar archivos temporales para un proceso determinado y ver su inode
y el directorio principal de inode.
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 así:
fd = anon_inode_getfd("random", &fops_anon, NULL, O_RDONLY | O_CLOEXEC);
y devuelve fd
al usuario, p. de un ioctl
.
Ahora el usuario tiene un fd
con file_operations
arbitrario asociado y inode
, y cuando ese fd
se cierra, todo se libera.
Este método es útil, p. si quieres tener múltiples read
syscalls, pero no quiere crear varios archivos de dispositivos, lo que contamina aún más /dev
:solo crea ioctl
extra s 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)
anon_inode
en /proc/PID/fd
Estas son tuberías y enchufes, consulte:https://unix.stackexchange.com/questions/463548/what-is-anon-inode-in-the-output-of-ls-l
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 un inodo de este tipo es así:
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.