Linux

管道的連結目標是否存在於文件系統中的某處?

  • June 22, 2021

我說的是這個:

$ readlink <(echo test)
pipe:[80076194]

pipe:[80076194]指向目標的路徑還是只是表明文件描述符已連接到管道並且文件系統中不存在?我問的主要原因是因為php有人試圖取消引用它:

$ strace -f php -r 'var_dump(file_get_contents($_SERVER["argv"][1]));' -- <(echo test)
...
[pid   654] lstat("/dev/fd/63", {st_mode=S_IFLNK|0500, st_size=64, ...}) = 0
[pid   654] readlink("/dev/fd/63", "pipe:[80095114]", 4096) = 15
[pid   654] lstat("/dev/fd/pipe:[80095114]", 0x7fff9c3628a0) = -1 ENOENT (No such file or directory)
[pid   654] lstat("/dev/fd", {st_mode=S_IFLNK|0777, st_size=13, ...}) = 0
[pid   654] readlink("/dev/fd", "/proc/self/fd"..., 4096) = 13
[pid   654] lstat("/proc/self/fd", {st_mode=S_IFDIR|0500, st_size=0, ...}) = 0
[pid   654] lstat("/proc/self", {st_mode=S_IFLNK|0777, st_size=64, ...}) = 0
[pid   654] readlink("/proc/self", "654"..., 4096) = 3
[pid   654] lstat("/proc/654", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid   654] lstat("/proc", {st_mode=S_IFDIR|0555, st_size=0, ...}) = 0
[pid   654] open("/proc/654/fd/pipe:[80095114]", O_RDONLY) = -1 ENOENT (No such file or directory)
[pid   654] write(2, "PHP Warning:  file_get_contents("..., 125PHP Warning:  file_get_contents(/dev/fd/63): failed to open stream: No such file or directory in Command line code on line 1
) = 125
[pid   654] write(1, "bool(false)\n", 12bool(false)
) = 12

簡而言之,不,它不存在。

 

長篇:

linux 中有 2 種類型的管道,命名管道(aka,fifo)和匿名管道。

命名管道是使用mkfifo( man 3 mkfifo) 系統呼叫創建的。命名管道作為文件存在於文件系統中。一個程序打開它進行讀取,另一個程序打開它進行寫入。

匿名管道是使用pipe( man 2 pipe) 系統呼叫創建的。一旦打開,它們的行為與打開 mkfifo 管道完全相同。它們佔用一個文件描述符,一端為讀打開,另一端為寫打開。

因為它們佔用了一個文件描述符,所以它們出現在/proc/PID/fd/. 但是由於它們在任何地方都不作為實際文件存在,因此輸入/proc/PID/fd/必須做一些魔術。所以基本上管道被表示為帶有假目標的符號連結。當您打開符號連結時,核心真正打開了符號連結所代表的管道。但是因為它是一個符號連結,並且符號連結有目標,所以任何試圖取消引用符號連結(不是通過核心隱式)的東西都會返回一個目標。只是這個目標沒有指向一個有效的文件。

通常你不能用符號連結來做到這一點,但是/proc文件系統不是一個普通的文件系統。這是一個由核心代表的假文件系統。而且由於內容是由核心創建的,核心可以打破自己的規則。

引用自:https://unix.stackexchange.com/questions/124970