断开的符号链接和一个神秘的(已删除)

问题描述 投票:3回答:2

我一直在使用linux上的proc文件系统,并且遇到了一些我想弄清楚的行为。

/proc中的每个进程都有一个指向其可执行文件/proc/{pid}/exe的符号链接。如果在删除可执行文件后进程继续运行,则读取此符号链接将返回到可执行文件的路径,并在末尾附加(deleted)

运行此命令,您甚至可能在系统上看到一些:

grep '(deleted)' <(for dir in $(ls /proc | grep -E '^[0-9]+'); do echo "$dir $(readlink /proc/$dir/exe)"; done)

我尝试使用一些简单的bash命令重新创建此行为:

>>> echo "temporary file" >> tmpfile.test
>>> ln -s tmpfile.test tmpfile.link
>>> rm tmpfile.test
>>> readlink tmpfile.link
tmpfile.test

名称后没有(deleted)!尝试cat tmpfile.link确认链接已断开(cat: tmpfile.link: No such file or directory)。

但是,同一天的同一天,确实导致(deleted)被附加到readlink的输出中。有什么用?

这是我想知道的:

  • 是否有一系列事件可以保证(deleted)附加到名称后?
  • 为什么/proc/{pid}/exe对于已删除的可执行文件显示(deleted)
  • 如何通过/proc/{pid}/exe获得可执行文件的名称没有任何附加的(deleted),并保证原始可执行文件不只是命名为some_executable (deleted)
linux bash symlink procfs
2个回答
2
投票

不是readlink,但是Linux将符号链接更改为指向<filename> (deleted),即(deleted)被附加到链接的目标。


0
投票

FWIW,特殊的<filename> (deleted)行为是在以下Linux内核函数d_path()中实现的:https://elixir.bootlin.com/linux/v4.1.13/source/fs/dcache.c#L3080

源注释(在下面的代码段中建议特殊行为仅适用于为某些“合成文件系统”(例如procfs)和“伪索引节点”即时生成的名称(路径)。

/**
 * d_path - return the path of a dentry
 * @path: path to report
 * @buf: buffer to return value in
 * @buflen: buffer length
 *
 * Convert a dentry into an ASCII path name. If the entry has been deleted
 * the string " (deleted)" is appended. Note that this is ambiguous.
 *
 * Returns a pointer into the buffer or an error code if the path was
 * too long. Note: Callers should use the returned pointer, not the passed
 * in buffer, to use the name! The implementation often starts at an offset
 * into the buffer, and may leave 0 bytes at the start.
 *
 * "buflen" should be positive.
 */
char *d_path(const struct path *path, char *buf, int buflen)
{
    char *res = buf + buflen;
    struct path root;
    int error;

    /*
     * We have various synthetic filesystems that never get mounted.  On
     * these filesystems dentries are never used for lookup purposes, and
     * thus don't need to be hashed.  They also don't need a name until a
     * user wants to identify the object in /proc/pid/fd/.  The little hack
     * below allows us to generate a name for these objects on demand:
     *
     * Some pseudo inodes are mountable.  When they are mounted
     * path->dentry == path->mnt->mnt_root.  In that case don't call d_dname
     * and instead have d_path return the mounted path.
     */
    if (path->dentry->d_op && path->dentry->d_op->d_dname &&
        (!IS_ROOT(path->dentry) || path->dentry != path->mnt->mnt_root))
        return path->dentry->d_op->d_dname(path->dentry, buf, buflen);

    rcu_read_lock();
    get_fs_root_rcu(current->fs, &root);
    error = path_with_deleted(path, &root, &res, &buflen);
    rcu_read_unlock();

    if (error < 0)
        res = ERR_PTR(error);
    return res;
}
© www.soinside.com 2019 - 2024. All rights reserved.