https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s3-proc-self.html 说
该
/proc/self/
目录是当前正在运行的进程的链接。
总是有多个进程同时运行,那么哪个进程是“当前正在运行的进程”?
考虑上下文切换,“当前正在运行的进程”与CPU上当前正在运行的进程有什么关系吗?
“当前正在运行的进程”与前台进程和后台进程无关吗?
https://www.centos.org/docs/5/html/5.2/Deployment_Guide/s3-proc-self.html 说
该
/proc/self/
目录是当前正在运行的进程的链接。
总是有多个进程同时运行,那么哪个进程是“当前正在运行的进程”?
考虑上下文切换,“当前正在运行的进程”与CPU上当前正在运行的进程有什么关系吗?
“当前正在运行的进程”与前台进程和后台进程无关吗?
Answers:
这与前台和后台进程无关。它只与当前正在运行的进程有关。当内核必须回答“ /proc/self
指向什么?”的问题时,它只选择当前调度的pid,即当前正在运行的进程(在当前逻辑CPU上)。结果是/proc/self
总是指向询问程序的pid。如果你跑
ls -l /proc/self
您会看到ls
的pid,如果您编写的代码使用/proc/self
该代码,则会看到其自己的pid等。
/proc/self
作为它的一个参数的路径名的一部分。
措词本来可以更好,但是您尝试组成的任何表达自我参照的措词都会使人困惑。我认为该目录的名称更具描述性。
基本上,它/proc/self/
代表正在阅读的过程/proc/self/
。因此,如果您尝试/proc/self/
从C程序打开,则它代表该程序。如果您尝试从外壳进行操作,则为外壳等。
但是,如果您有一个四核CPU能够同时运行4个进程,而不是真正执行多任务处理,该怎么办?
然后,每个过程将看到一个/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 Device Drivers”一书中阅读有关如何进行操作的信息。它甚至可以作为在线软拷贝获得。
/proc/self
不是设备驱动程序,而是一个称为的内核暴露文件系统的一部分procfs
。
/proc
在古老的“ Linux设备驱动程序”一书中甚至有一个基于驱动程序的示例实现。我应该知道,我在大学里实施了一个。我可能本来可以用术语“内核模块”来代替,但是“设备驱动程序”是大多数人所熟悉的,我不想给人以误解的印象,即“内核模块”和“设备驱动程序”之间存在显着差异。除了术语。
无论碰巧正在访问的是哪个过程,/proc/self
还是其中的文件/文件夹。
尝试cat /proc/self/cmdline
。您会惊奇地发现,cat /proc/self/cmdline
(实际上,而不是空格之间,t
和之间将有一个空字符/
),因为它将是访问此伪文件的cat进程。
执行时ls -l /proc/self
,您将看到ls进程本身的pid。或怎么样ls -l /proc/self/exe
?它将指向ls可执行文件。
或者尝试一下,以进行更改:
$ cp /proc/self/cmdline /tmp/cmd
$ hexdump -C /tmp/cmd
00000000 63 70 00 2f 70 72 6f 63 2f 73 65 6c 66 2f 63 6d |cp./proc/self/cm|
00000010 64 6c 69 6e 65 00 2f 74 6d 70 2f 63 6d 64 00 |dline./tmp/cmd.|
0000001f
甚至
$ hexdump -C /proc/self/cmdline
00000000 68 65 78 64 75 6d 70 00 2d 43 00 2f 70 72 6f 63 |hexdump.-C./proc|
00000010 2f 73 65 6c 66 2f 63 6d 64 6c 69 6e 65 00 |/self/cmdline.|
0000001e
正如我所说的,无论是正在访问的进程/proc/self
还是其中的文件/文件夹。
/ 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,因为这是进程的PID-新创建的/ bin / ls进程-读取目录的内容。但是,在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只处理字符串,它从不馈送给任何与路径名相关的syscall。
现在,考虑以下情况:
root@vps01:~# cd /proc/self/fd
root@vps01:~# ls
0 1 2 255
在这里,shell 是 / bin / ls 的父进程,将/ proc / self的子目录作为其当前目录。因此,从其角度评估相对路径名。我最好的猜测是,这与POSIX文件的语义有关,您可以在其中创建到文件的多个硬链接,包括任何打开的文件描述符。因此,这次,/ bin / ls的行为类似于echo / proc / $$ / fd / *。
/proc/self
当然,评估的过程。