如何在内核(库)中实现getcwd?

时间:2015-03-30 07:42:24

标签: c directory kernel pwd

一个过程可以做到

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

来自另一个shell

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

第一个过程

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

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

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

修改

可能问题是模糊 - 试图改进它。一种可能的情况(来自所知道的)

  1. 内核知道给定进程(及其线程)的CWD的inode - 例如inode号1000
  2. 读取inode(获取需要阅读的块)
  3. 读取相应的块(例如打开目录)
  4. 读取目录条目(条目名称和inode编号)
  5. 获取..父目录的inode编号(例如900)和.(当前目录)的inode编号
  6. 读取获取的父目录的内容
    • 上一个目录的name(对于inode 1000
    • 父目录的inode编号
  7. 继续5. - 直到达到根节点。
  8. 这意味着,getcwd

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

    采用了更多原始IO操作(需要读取更多目录条目)和短

    /tmp
    

    整个getcwd由两个读数完成?

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

2 个答案:

答案 0 :(得分:1)

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

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

然而,出现了许多问题 - 很少有问题:

  • 正如你所说 - 太复杂的路径名解析(是的,对于更深层目录需要更多IO)
  • 取决于只存在一个ROOT目录的前提。这在BSD 4.2中是不正确的,其中引入了per process根目录 - 允许chroot系统调用的内容 - 允许将根设置到任何目录而不显示进程的真实路径。 (最酷的FreeBSD功能之一是 jails - 取决于此)(同样古老的linux只有一个根 - 只在0.96c中引入了VFS - 虚拟文件系统层)
  • 和许可问题 - 例如
  • 时会发生什么
#shell1
$ mkdir -p /tmp/some
$ cd /tmp/some

第二个shell

$ 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

e.g。系统允许你在"当前"目录,不知道你在哪里。 (在两种情况下,例如在chroot和第二种情况下);)

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

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

  • 内核维护另一个全局表,(在linux中称为 dentry (目录条目)), - 内核维护" inode" - > "路径"映射每个进程,每个打开的文件描述符,以及indode缓存(在由内核本身维护的linux中,BSD:vnod驱动程序的作业)等。

E.g。当某个进程请求inode X的路径名时,内核搜索dentry表,如果找到了条目 - 如果没有则立即返回 - 调用lookup进程,执行路径名的是什么分辨率

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

以上都是非常简化,正如您自己所看到的,以上都是高度依赖于操作系统,共同基础由POSIX定义 - 但后面发生(例如实现) - 您需要真正阅读内核和/或谷歌的来源:

  • linux dentry
  • linux vfs
  • freebsd vnode
  • 路径名解析

等。

Ps:对于nitpickers,:) - 正如我所说 - 一切都过于简单,所以如果你想要正确并添加更多细节 - 编辑答案 - 我将其转换为"社区维基回答"

答案 1 :(得分:0)

在当前的POSIX内核(如Linux(或* BSD-s))中,当前工作目录(作为内核inode)是process状态的一部分。因此,内核中的进程描述符(可能是Linux上的一些struct task_struct)包含或引用该cwd。那么getcwd就是"简直就是#34;系统调用查询。

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

当然,邪恶在于细节!