APUE 说
每个进程还有一个根目录,用于解析绝对路径名。可以使用 chroot 功能更改此根目录。
我认为只有相对路径名需要解析。所以我想知道
绝对路径名的解析是什么意思?
如何
chroot
使用根目录来解析绝对路径名?谢谢。
答案1
所有路径名都需要解析。显然,进程将路径名作为系统调用的参数传递给内核,例如:
creat
或者open
,link
或者rename
,unlink
或者rmdir
,chmod
或者chown
,chdir
或者chroot
,execve
,
等等。考虑一个看起来像这样的路径名
……
a
/
b
/
c
内核对此的解释方式是:
开始(在文件系统中的某个位置),
查找名为a
1 的目录。
如果没有找到,则返回错误。
如果找到,则在该目录中搜索名为 的子目录b
。
如果没有找到,则返回错误。如果找到,则在该目录中搜索名为2 的
目录条目。 如果没有找到,则返回错误3。 如果找到,则返回该索引节点。c
请注意路径名开头和算法第一行的混淆。很简单:如果路径名以斜杠开头(即,它是“绝对路径名”,例如,/a/b/c
),则搜索从进程的根目录开始,如果路径名以其他任何内容开头(即,它是相对路径名,例如, a/b/c
),搜索从进程的当前工作目录开始。
你可能会问“这是如何实现的?”嗯,当然,内核维护着每个进程的很多信息,包括
- PID、PPID和各种进程组标识符,
- 真实、有效、保存的UID和GID,以及补充GID列表,
- 打开文件,
- 信号配置,
和更多。我遗漏了很多东西,因为它们与这个问题无关。我省略了环境变量,因为它们不是由内核维护的;它们由用户空间程序维护。内核所做的只是支持一种通过 .NET 将环境变量从一个程序传递到另一个程序的机制execve
。
出于戏剧性的目的,我在上面的列表中遗漏了两件事:
- 进程的根目录,以及
- 当前工作目录
这些是指向 inode 的指针。我希望每个已经了解了这一步的人都了解如何设置进程的当前工作目录 - 进程调用chdir
,将路径名作为参数传递给它;内核按照上述过程解释路径名(将其解析为索引节点),并在成功后将当前目录指针设置为指向该索引节点。
进程的根目录以相同的方式设置,除了chroot
系统调用之外。
(请注意,无论哪种情况,如果路径名参数以 开头/
,则路径名解析从进程的根目录开始
调用系统调用时生效。 )
一些例子:
- 如果您的当前目录是
/home/tim
(并且您的进程根目录是文件系统根目录),那么- 如果您访问
/etc/services
,您将获得/etc/services
, - 如果您访问
.bashrc
,您将获得/home/tim/.bashrc
。
- 如果您访问
- 如果您这样做
chroot /filesystem/tim
(假设有一个同名的目录,并且您有权访问它,并且您有必要的权限chroot
),那么- 如果您访问
/etc/services
,您将获得/filesystem/tim/etc/services
, - 如果你访问
/
,你就会得到/filesystem/tim
,所以 - 如果你
chroot /
,什么都不会改变; - 如果你这样做
chroot /filesystem/john
,它会尽力chroot
去做/filesystem/tim/filesystem/john
。
- 如果您访问
由于根目录和当前目录存储为指向 inode 的指针,因此系统不需要“定位”它们。
__________
1 即,查找指向某个 inode 的目录项,该 inode 的模式表明它是一个目录,即(i_mode & IFMT) == IFDIR
。
creat(file, mode)
open(file, O_CREAT, mode)
答案2
例如,当内核解析/usr/share/man/man1/cat.1.gz
为 inode 时,它将必须从 root 开始/
,一直向下到cat.1.gz
。如果是相对路径名,则只需在当前目录中查找文件即可。
也许您正在考虑如何获取当前工作目录的绝对路径?要确定路径,您必须从当前目录开始,通过所有中间目录直至根目录。 (但请注意,当给定文件的相对路径(例如作为系统调用的参数)时,内核不会执行此操作open
。)