1

一个过程可以做

chdir("/to/some/where");

当从另一个外壳

mv /to/some/where /now/different/path/

第一个过程

print getcwd(); 
#prints /now/different/path/

是如何getcwd实施的?(在最低级别,例如在内核级别,inode ...)。

我知道常见的(基于inode 的)文件系统是如何工作的,例如包含目录的内容(条目名称和相应的inode 编号)。

编辑

可能问题是模糊的 - 试图完善它。一种可能的情况(据我们所知)

  1. 内核知道CWD给定进程(和他的线程)的inode - 例如inode number1000
  2. 读取 inode(获取需要读取的块)
  3. 读取相应的块(例如打开目录)
  4. 读取目录条目(条目名称和 inode 编号)
  5. 获取..父目录(例如900)的 inode 号和.(当前目录)的 inode 号
  6. 读取获取的父目录的内容
  • name一个目录的(对于 inode 1000
  • 父目录的inode号
  1. 继续5.- 直到到达根 inode。

也就是说,getcwd对于

/some/very/very/very/deep/directory/level

需要更多原始 IO 操作(需要读取更多目录条目)

/tmp

整体getcwd是由两个读数完成的?

这个对吗?还是完全以另一种方式完成?

4

2 回答 2

1

首先,你问错地方了。这个问题更多是关于操作系统的,所以unix.stackexchange是更好的地方。

无论如何,您提出的解决方案对于某些古老的 UNIX 实现(例如 BSD 2.8)或类似的实现是正确的。可以按照您的描述完成该路径名解析。

但是,出现了许多问题 - 其中很少:

  • 正如你所说 - 太复杂的路径名解析(是的,对于更深的目录需要更多的 IO)
  • 取决于只存在一个ROOT目录的前提。per process从引入根目录的 BSD 4.2 来看,情况并非如此- 允许chroot系统调用 - 允许将根设置为任何目录而不显示进程的真实路径。(最酷的 FreeBSD 功能之一是监狱- 取决于此)(古代 linux 也只有一个根 - 仅在 0.96c 中引入了 VFS - 虚拟文件系统层)
  • 和许可问题 - 例如,当
#shell1
$ mkdir -p /tmp/some
$ cd /tmp/some

第二壳

$ su
# mkdir -p /tmp/my
# chmod 700 /tmp/my
# mv /tmp/some /tmp/my/

/tmp/my目录对于第一个进程不可读。所以,它无法确定路径,那么它应该如何处理文件呢?因此,再次在 shell1 中:

$ pwd
/tmp/some #the original
$ echo $CWD
/tmp/some
$ /bin/pwd
pwd: .: Permission denied

但是,你仍然可以做例如

$ touch bob #works

例如,系统允许您在“当前”目录中工作,而不会让您知道您在哪里。(在这两种情况下,例如在 chroot 和第二种情况下);)

这意味着每个进程都将当前工作目录存储在他的表中:

  • 设备号(例如 hdd1 或 hdd2)
  • 设备上的 inode 编号

  • 内核维护另一个全局表(在 linux 中称为dentry(目录条目)),内核维护每个进程、每个打开的文件描述符以及 indode 缓存的“inode”->“path”映射(在内核自己维护的linux中,BSD:job for the vnoddriver)之类的。

例如,当某个进程要求输入节点 X 的路径名时,内核会搜索dentry表,如果找到该条目 - 立即返回,如果没有 - 调用该lookup进程,如何解析路径名

例如,当发生重命名时,内核会搜索dentry表,如果找到条目并根据需要进行更改。

如您所见,以上所有内容都非常简化,以上所有内容都高度依赖于操作系统,通用基础由 POSIX 定义-但发生在后面(例如实现)-您需要真正阅读内核和/或谷歌的源代码:

  • linux 目录
  • linux vfs
  • freebsd vnode
  • 路径名解析

等等。

Ps:对于挑剔者,:) - 正如我所说 - 一切都过于简单,所以如果你想要更正并添加更多细节 - 编辑答案 - 我将其转换为“社区 wiki 答案”。

于 2015-03-30T10:18:36.787 回答
0

在当前的 POSIX 内核如 Linux(或 *BSD-s)中,当前工作目录(作为内核 inode)是进程状态的一部分。所以内核进程描述符(可能是struct task_structLinux上的一些)包含或引用该cwd。然后getcwd是“简单”的系统调用查询。

内核 inode(用于打开的文件描述符,包括工作目录)与文件系统相关,与磁盘 inode 不同。

当然,邪恶在细节中!

于 2015-03-30T08:00:22.377 回答