GNU/Linux >> Linux Esercitazione >  >> Linux

Cos'è un inode anonimo in Linux?

open con O_TMPFILE

Questa sarebbe una buona definizione di inode anonimo:crea un inode all'interno di una data directory senza alcun nome, che non appare affatto con ls .

Quindi, quando chiudi il descrittore, il file viene eliminato.

È stato aggiunto in 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 a monte.

Compila ed esegui:

gcc -o main.out -std=c99 -Wall -Wextra -pedantic  main.c
./main.out

Questo è quindi essenzialmente il modo ottimale per implementare i file temporanei:Come creare un file di testo temporaneo in C++? come può:

  • trova sempre immediatamente un nome libero senza che dobbiamo ripetere i nomi dei file (non è necessario alcun nome!)
  • e ha l'eliminazione automatica

Confrontalo con un metodo più manuale per le directory come quello mostrato in:Come creare una directory temporanea in C++?

Testato su Ubuntu 17.04, Linux 4.10, glibc 2.24.

Come O_TMPFILE sembra in /proc/PID/fd

Possiamo esaminarlo rapidamente 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();
}

quindi per un output di esempio:

pid 15952     
inode 44698689

facciamo:

ls -l /proc/15952/fd

e che contiene:

3 -> '/home/ciro/test/#44698689 (deleted)'

che ci mostra come trovare i file temporanei per un determinato processo e vedere il loro inode e directory principale inode.

anon_inode_getfd Funzione kernel Linux

Se hai a che fare con i moduli del kernel, questa è una definizione probabile.

Lo chiami come:

fd = anon_inode_getfd("random", &fops_anon, NULL, O_RDONLY | O_CLOEXEC);

e restituisce fd all'utente, ad es. da un ioctl .

Ora l'utente ha un fd con file_operations arbitrario associato e inode , e quando quel fd è chiuso, tutto è liberato.

Questo metodo è utile ad es. se vuoi avere più read syscalls, ma non voglio creare più file di dispositivo, il che inquina ulteriormente /dev :devi solo creare ioctl extra s invece.

Esempio eseguibile minimo 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 in /proc/PID/fd

Questi sono pipe e socket, vedi:https://unix.stackexchange.com/questions/463548/what-is-anon-inode-in-the-output-of-ls-l


Almeno in alcuni contesti, un inode anonimo è un inode senza una voce di directory allegata. Il modo più semplice per creare un tale inode è come tale:

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.

Linux
  1. Linux vs. Unix:qual è la differenza?

  2. Cosa c'è di nuovo con rdiff-backup?

  3. Che cos'è un utente Linux?

  4. Cos'è Umask in Linux

  5. Migrazione da Unix a Linux

Cosa mi dice il mio prompt dei comandi di Linux?

Cosa fare in caso di panico del kernel Linux

Che cos'è Login Shell in Linux?

Che cos'è la media del carico in Linux?

Cosa sono gli inode in Linux?

Che cos'è il file .bashrc in Linux?