原文如下。见4.22节
图4.24中的程序更改为特定目录,然后调用
getcwd
以打印工作目录。如果我们运行该程序,我们得到$ ./a.out cwd = /var/spool/uucppublic $ ls -l /usr/spool lrwxrwxrwx 1 root 12 Jan 31 07:57 /usr/spool -> ../var/spool
请注意,chdir遵循我们期望的符号链接,如图4.17所示。但是当它上升到目录树时,getcwd不知道它何时到达/ var / spool目录,它是由符号指向的链接/ usr / spool。这是符号链接的特征。
作者真正的意思是说该程序命中/var/spool
?
作者指出的符号链接的特征是什么?
我真的不明白。
答案 0 :(得分:2)
假设您有一个指向/usr/spool
的符号链接/var/spool
。
它表示如果您遵循该符号链接(例如cd /usr/spool
),您最终会进入指向目录(/var/spool
)。然后,您遵循符号链接的信息将丢失。您就在/var/spool
,就像您直接完成了cd /var/spool
一样。
另一个cd ..
会将您带到/var
(而不是/usr
)。
更新:
正如Keith Thompson和Jonathan Leffler所指出的,有一些做的shell会记住你所遵循的路径(即/usr/spool
)。在这样的炮弹中,cd ..
会去/usr/
。但是,从这样的shell启动的程序仍然会将/var/spool
视为工作目录。
这可能是作者允许您编写用于显示cwd
的程序(以解决此类shell'内部)的原因。
答案 1 :(得分:2)
扩展@undor_gongor所写的内容:
每个进程都有一个当前工作目录。它不存储为目录的路径名;它是对目录本身的引用。
如果它被存储为路径名,那么getcwd()
函数的作业将是微不足道的:只需打印路径名。相反,它必须读取当前目录,打开其..
条目,然后打开该目录的..
条目,依此类推,直到它到达根目录(即,..
条目的目录指向目录本身)。它以相反的顺序构建当前目录的完整路径。
由于..
不能是符号链接,因此此过程不受符号链接的影响。
(Shell可能有一个$PWD
或$CWD
变量,或者pwd
内置的,受符号链接影响;这些通常通过记住传递给{的字符串来工作{1}}或cd
。)
答案 2 :(得分:2)
请注意,某些shell(尤其是bash
)通过追踪符号链接来跟踪您是否到达给定目录,并相应地打印当前目录。至少bash
可以选择cd
来执行物理或逻辑更改目录:
cd [-L|-P] [dir]
将当前目录更改为dir。变量HOME是默认目录。 [...]
-P
选项表示使用物理目录结构而不是跟随符号链接(另请参阅set builtin命令的-P
选项);-L
选项强制遵循符号链接。-
的参数等价于$ OLDPWD。如果使用CDPATH中的非空目录名,或者-
是第一个参数,并且目录更改成功,则新工作目录的绝对路径名将写入标准输出。如果目录已成功更改,则返回值为true;否则就是假的。
在显示的方案中,/usr/spool
是/var/spool
的符号链接,然后:
$ pwd
/
$ cd /usr/spool/uucppublic
/usr/spool/uucppublic
$ cd -L ..
/usr/spool
$ cd /usr/spool/uucppublic
/usr/spool/uucppublic
$ cd -P ..
/var/spool
$
对于大多数人来说,普通cd ..
与cd -L ..
的做法相同。如果您愿意,可以选择bash
与cd -P ..
相同(使用set -P
或set -L
)。
还应该了解查找当前目录的路径名的过程。逻辑上,进程(内核)打开当前目录(.
)并读取inode编号(和设备编号)。然后打开父目录(..
),并从中读取条目,直到找到具有匹配的inode编号(和设备编号)的条目。然后,它为它提供路径名的最后一个组件。它现在可以重复该过程,找到下一个目录的inode编号,并打开其父目录(../..
)等,直到它到达根目录(两个{{1}的inode编号) }和.
是相同的,值通常为2)。请注意,这甚至适用于挂载点。但请注意自动安装的远程(NFS)文件系统;如果你扫描一个包含数百个自动安装机器的目录,它可能会非常慢 - 因为上面的天真搜索大纲会安装所有机器,直到它找到正确的机器。因此,实际的..
函数比这更聪明,但它解释了如何找到当前目录的路径。它还说明了在评估getcwd()
下的目录时,流程不会遇到/usr/spool
的原因 - 它根本不会打开/var/spool/uucppublic
目录。
请注意,/usr
函数(系统调用)采用可能引用符号链接的名称,并将其解析为根本不包含符号链接的名称。通过realpath()
后,它会返回/usr/spool/uucppublic
,例如。