GNU/Linux >> Tutoriels Linux >  >> Linux

Qu'est-ce qu'un inode anonyme sous Linux ?

open avec O_TMPFILE

Ce serait une bonne définition de l'inode anonyme :il crée un inode dans un répertoire donné sans aucun nom, qui n'apparaît pas du tout avec ls .

Ensuite, lorsque vous fermez le descripteur, le fichier est supprimé.

Il a été ajouté dans 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 en amont.

Compiler et exécuter :

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

C'est donc essentiellement la manière optimale d'implémenter des fichiers temporaires :Comment créer un fichier texte temporaire en C++ ? comme il peut :

  • Trouvez toujours immédiatement un nom libre sans que nous ayons à boucler sur les noms de fichiers (aucun nom n'est nécessaire !)
  • et a une suppression automatique

Comparez cela à une méthode plus manuelle pour les répertoires comme celle illustrée à :Comment créer un répertoire temporaire en C++ ?

Testé sous Ubuntu 17.04, Linux 4.10, glibc 2.24.

Comment O_TMPFILE ressemble à /proc/PID/fd

Nous pouvons l'examiner rapidement avec :

#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();
}

puis pour un exemple de sortie :

pid 15952     
inode 44698689

nous faisons :

ls -l /proc/15952/fd

et qui contient :

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

qui nous montre comment trouver des fichiers temporaires pour un processus donné et voir leur inode et le répertoire parent de l'inode.

anon_inode_getfd Fonction du noyau Linux

Si vous avez affaire à des modules du noyau, il s'agit probablement d'une définition.

Vous l'appelez comme :

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

et renvoie fd à l'utilisateur, par ex. depuis un ioctl .

L'utilisateur a maintenant un fd avec file_operations arbitraire associé et inode , et quand ce fd est fermé, tout est libéré.

Cette méthode est utile par ex. si vous voulez avoir plusieurs read syscalls, mais ne veulent pas créer plusieurs fichiers de périphérique, ce qui pollue davantage /dev  :vous créez simplement des ioctl supplémentaires s à la place.

Exemple exécutable minimal avec 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 dans /proc/PID/fd

Ce sont des tuyaux et des sockets, voir :https://unix.stackexchange.com/questions/463548/what-is-anon-inode-in-the-output-of-ls-l


Au moins dans certains contextes, un inode anonyme est un inode sans entrée de répertoire attachée. La manière la plus simple de créer un tel inode est la suivante :

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. Quoi de neuf avec rdiff-backup ?

  2. Qu'est-ce qu'un utilisateur Linux ?

  3. Migration d'Unix vers Linux

  4. Qu'est-ce qu'un numéro d'inode sous Linux ?

  5. Linux - Modifier les autorisations de dossier ?

Qu'est-ce que mon invite de commande Linux me dit?

Que faire en cas de panique du noyau Linux

Qu'est-ce que le shell de connexion sous Linux ?

Qu'est-ce que la moyenne de charge sous Linux ?

Que sont les inodes sous Linux ?

Qu'est-ce qu'un fichier .bashrc sous Linux ?