shell如何知道它所在的目录?

4
我一直在尝试弄清楚shell如何知道你当前所在的目录。我知道有一个环境变量$PWD,但当我尝试手动更改它时,它只会改变我的shell提示符显示的内容,而像ls和cd这样的命令则不受影响。
cd是一个内部shell命令,因此我可以理解它可能使用存储在shell内存中的信息,但ls是外部命令,然而运行ls而不带任何参数将给我显示原来所在的目录,无论我对$PWD做了什么。
5个回答

12

每个进程都有自己的当前工作目录,Linux系统会跟踪它。这是操作系统为每个进程管理的信息之一。有一个系统调用getcwd()可以检索此目录。

$PWD环境变量反映了shell上次检查时getcwd()的内容,但更改它并不会真正更改当前目录。要实现这一点,shell必须在$PWD更改时调用chdir(),但它并没有这样做。

这也是为什么cd必须是shell内置命令的原因。当您运行子进程时,该子进程将拥有自己的工作目录,因此如果cd是可执行文件,则其对chdir()的调用将无效,因为这不会更改其父目录的工作目录。它只会更改自己(短暂的)工作目录。因此,cd是shell内置的,以避免启动子进程。


6
有趣的旁白:根据《UNIX历程25年》(我想是这本书),在非常古老的Unix中,chdir实际上确实是一个外部进程。这是因为没有wait命令,shell仅仅exec它运行的程序,然后在退出时重新exec shell。这意味着/bin/chdir可以简单地执行chdir(),然后重新exec shell,从而继承新的CWD。 :) - hobbs
哎呀,我的反引号失控了,现在已经太晚编辑了 ;) - hobbs
Linux(Solaris,...)有/proc文件系统,您可以实际“看到”这些内容。要获取您的shell的cwd,请使用ls -ld /proc/$$/cwd(shell将其进程ID替换为$$)。 - Tony Delroy

9
这个变量是由shell设置的,但它会在内部存储(这就是为什么你不能将cd作为外部程序,它必须是内置的)。每次显示shell提示符之前,shell都会组合它,并且你已经使用了$PWD指定了它,所以shell会读取它。记住:shell只是像其他程序一样的程序。它可以并且确实会将东西存储在变量中。
正如AndiDogJohn指出的那样,类Unix系统(包括Linux)通过一组系统调用来维护每个进程的工作目录。然而,存储仍然是进程本地的。

3

Linux内核会存储每个进程的当前目录。你可以在/proc文件系统中查找它(例如,对于init进程,“/proc/1/cwd”)。

使用chdir系统调用可以更改当前目录,并使用getcwd获取它。


1
你(OP)通过命令行启动ls,并且任何你启动的进程都是在当前工作目录的上下文中启动的。因此,每个你启动的进程都有它自己的$PWD变量(以某种方式)。

1
main函数(int argc, char **argv, char **envp)有一个很少用到的参数,曾经是第三个参数,即环境变量被操作系统复制到主函数中启动进程,但现在大多数系统都会自动完成这一过程,因此已经被废弃。 - t0mm13b

1

当前目录是正在运行的程序(进程)的属性,由该进程创建的进程继承它。通过操作系统调用来更改当前目录。Shell将cd操作映射到该系统调用。当您编写像ls这样的外部程序时,该程序会继承当前目录。

$PWD变量是Shell向您显示当前目录以便您将其用作变量(如果需要)的方式。更改它不会影响Shell本身的实际当前目录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接