https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s3-proc-self.html 说
该
/proc/self/
目录是当前正在运行的进程的链接。
总是有多个进程同时运行,那么哪个进程是“当前运行的进程”呢?
考虑到上下文切换,“当前正在运行的进程”与当前在 CPU 上运行的进程有什么关系吗?
“当前运行的进程”与前台和后台进程无关吗?
答案1
这与前台和后台进程无关;它只与当前正在运行的进程有关。当内核必须回答“它指向什么/proc/self
?”这个问题时,它只需选择当前调度的pid,IE当前正在运行的进程(在当前逻辑 CPU 上)。其效果是/proc/self
始终指向发出请求的程序的 pid;如果你跑
ls -l /proc/self
你会看到ls
的 pid,如果你编写使用/proc/self
该代码的代码将看到它自己的 pid 等。
答案2
访问符号链接的一个(在其上调用 readlink() ,或在通过它的路径上调用 open() )。当时它会在 CPU 上运行,但这并不相关。多处理器系统可以同时在 CPU 上运行多个进程。
前台和后台进程主要是一种 shell 构造,并且也没有唯一的前台进程,因为系统上的所有 shell 会话都会有一个。
答案3
措辞本来可以更好,但话又说回来,你试图撰写的任何措辞来表达自我引用的想法都会令人困惑。我认为目录的名称更具描述性。
基本上,/proc/self/
代表正在阅读的过程/proc/self/
。因此,如果您尝试/proc/self/
从 C 程序打开,那么它就代表该程序。如果您尝试从外壳执行此操作,那么它就是外壳等。
但是,如果您有一个真正能够同时运行 4 个进程而不是多任务处理的四核 CPU,该怎么办?
然后每个进程都会看到不同的/proc/self/
真实情况,而无法看到彼此的/proc/self/
。
这是如何运作的?
嗯,/proc/self/
实际上并不是一个文件夹。它是一个设备驱动程序,如果您尝试访问它,它会将自己暴露为文件夹。这是因为它实现了文件夹所需的 API。目录/proc/self/
并不是唯一执行此操作的东西。考虑从远程服务器安装共享文件夹或安装 USB 拇指驱动器或保管箱。它们都通过实现相同的 API 集来工作,使它们的行为类似于文件夹。
当进程尝试访问设备驱动程序时/proc/self/
,设备驱动程序将通过从该进程读取数据来动态生成其内容。所以里面的文件/proc/self/
并不真正存在。它有点像一面镜子,会反射出试图观察它的过程。
它真的是设备驱动程序吗?听起来你把事情过于简单化了!
是的,确实如此。如果你想迂腐一点,那就是内核模块。但是,如果您查看各种 Linux 开发人员频道上的 usenet 帖子,大多数内核开发人员会互换使用“设备驱动程序”和“内核模块”。我曾经为 Linux 编写设备驱动程序,呃……内核模块。如果您想在 中编写自己的界面/proc/
,例如您想要一个/proc/unix.stackexchange/
从该网站返回帖子的文件系统,您可以在 O'Reilly 出版的著名的“Linux 设备驱动程序”书中了解如何做到这一点。它甚至可以在线获取软拷贝。
答案4
/proc/self 是语法糖。这是连接 /proc/ 和 getpid() 系统调用结果的快捷方式(在 bash 中可作为元变量 $$ 访问)。不过,在 shell 脚本编写的情况下,这可能会令人困惑,因为许多语句调用其他进程,并带有自己的 PID...PID 通常指的是死进程。考虑:
root@vps01:~# ls -l /proc/self/fd
total 0
lrwx------ 1 root root 64 Jan 1 01:51 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 1 01:51 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jan 1 01:51 2 -> /dev/pts/0
lr-x------ 1 root root 64 Jan 1 01:51 3 -> /proc/26562/fd
root@vps01:~# echo $$
593
'/bin/ls' 将评估目录的路径,将其解析为 /proc/26563,因为这是读取目录内容的进程(新创建的 /bin/ls 进程)的 PID。但是,当管道中的下一个进程(如果是 shell 脚本)或提示符返回(如果是交互式 shell)时,该路径不再存在信息输出是指不存在的过程。
然而,这只适用于外部命令(那些是实际的可执行程序文件,而不是内置到 shell 本身中)。因此,如果您使用文件名通配来获取目录内容的列表,而不是将路径名传递给外部进程 /bin/ls,您将得到不同的结果:
root@vps01:~# ls /proc/self/fd
0 1 2 3
root@vps01:~/specs# echo /proc/self/fd/*
/proc/self/fd/0 /proc/self/fd/1 /proc/self/fd/2 /proc/self/fd/255 /proc/self/fd/3
在第一行中,shell 通过 exec() 系统调用生成一个新进程“/bin/ls”,并将“/proc/self/fd”作为 argv[1] 传递。 '/bin/ls' 依次打开目录 /proc/self/fd 并在迭代时读取并打印其内容。
然而,第二行在幕后使用 glob() 来扩展文件名列表;它们作为字符串数组传递以进行回显。 (通常作为内部命令实现,但通常还有一个 /bin/echo 二进制文件......但这部分实际上无关紧要,因为 echo 只处理字符串,它永远不会提供给与路径名相关的任何系统调用。)
现在,考虑以下情况:
root@vps01:~# cd /proc/self/fd
root@vps01:~# ls
0 1 2 255
在这里,外壳,的父进程/bin/ls,已将 /proc/self 设为其子目录当前目录。因此,相对路径名是从其角度进行评估的。我最好的猜测是,这与 POSIX 文件语义有关,您可以在其中创建指向文件的多个硬链接,包括任何打开的文件描述符。所以这一次 /bin/ls 的行为与 echo /proc/$$/fd/* 类似。