Joe*_*Joe 28 linux filesystems devices
这是一个相当低级的问题,我知道这可能不是最好的提问地点。但是,它似乎比任何其他 SE 网站都更合适,所以就这样吧。
我知道在 Linux 文件系统上,确实存在一些文件,例如:/usr/bin/bashis one that exists。然而,(据我所知),有的还没有实际存在本身和更虚拟的文件,如:/dev/sda,/proc/cpuinfo等我的问题是(它们是两个,而是要独立的问题也密切相关):
/dev/random将返回随机数据,读取自/dev/null将返回EOF. 它如何确定要从该虚拟文件中读取哪些数据(以及因此当/如果数据也写入虚拟文件时要做什么) - 是否有某种带有指向适合每个文件的单独读/写命令的指针的映射,甚至是虚拟目录本身?因此,一个条目/dev/null可以简单地返回一个EOF.Tom*_*unt 25
所以这里基本上有两种不同类型的东西:
/proc和/sys是这里的示例,FUSE 自定义文件系统(如sshfs或ifuse. 其中有更多的多样性,因为实际上它们只是指具有某种意义上“自定义”语义的文件系统。因此,当您从 下的文件中读取时/proc,您实际上并没有像在普通文件系统下那样访问由其他人早先写入它存储的特定数据。您实际上是在进行内核调用,请求一些即时生成的信息。并且这段代码可以做任何它喜欢的事情,因为它只是在某处实现read语义的某个函数。因此,您在 下有文件的奇怪行为,/proc例如在它们不是时假装是符号链接关键是这/dev实际上通常是第一种。在现代发行版中,/dev像 tmpfs 这样的东西是很正常的,但在旧系统中,它是磁盘上的普通目录,没有任何特殊属性是正常的。关键是下面的文件/dev是设备节点,一种类似于FIFOs或Unix sockets的特殊文件;设备节点有主要和次要编号,读取或写入它们是对内核驱动程序的调用,就像读取或写入 FIFO 是调用内核在管道中缓冲输出一样。这个驱动程序可以做任何它想做的事情,但它通常以某种方式接触硬件,例如访问硬盘或在扬声器中播放声音。
要回答原始问题:
有两个与“文件是否存在”相关的问题;这些是设备节点文件是否确实存在,以及支持它的内核代码是否有意义。前者就像普通文件系统上的任何东西一样被解决。现代系统使用udev或类似的东西来监视硬件事件并相应地自动创建和销毁设备节点/dev。但是较旧的系统或轻量级定制版本可以将所有设备节点直接放在磁盘上,并提前创建。同时,当您阅读这些文件时,您正在调用由主设备号和次设备号确定的内核代码;如果这些不合理(例如,您试图读取一个不存在的块设备),您只会收到某种 I/O 错误。
它计算出调用哪个设备文件的内核代码的方式有所不同。对于虚拟文件系统,如/proc,他们实现自己的read和write功能; 内核只是根据它所在的挂载点调用该代码,文件系统实现负责其余部分。对于设备文件,它根据主要和次要设备号进行调度。
Bru*_*ger 17
这是/dev/sda1我几乎最新的 Arch Linux 服务器上的文件列表:
% ls -li /dev/sda1
1294 brw-rw---- 1 root disk 8, 1 Nov 9 13:26 /dev/sda1
Run Code Online (Sandbox Code Playgroud)
所以/dev/for中的目录条目sda有一个inode号,1294。它是磁盘上的一个真实文件。
查看文件大小通常出现的位置。而是出现“8, 1”。这是一个主要和次要设备号。还要注意文件权限中的“b”。
该文件/usr/include/ext2fs/ext2_fs.h包含此(片段)C 结构:
/*
* Structure of an inode on the disk
*/
struct ext2_inode {
__u16 i_mode; /* File mode */
Run Code Online (Sandbox Code Playgroud)
该结构向我们展示了文件 inode 的磁盘结构。这个结构中有很多有趣的东西;看看它。
的i_mode元素struct ext2_inode有 16 位,它只使用 9 位用于用户/组/其他、读/写/执行权限,另外 3 位用于 setuid、setgid 和粘性。它有 4 位来区分“普通文件”、“链接”、“目录”、“命名管道”、“Unix 系列套接字”和“块设备”等类型。
Linux 内核可以遵循通常的目录查找算法,然后根据i_mode元素中的权限和标志做出决定。对于“b”,块设备文件,它可以找到主设备号和次设备号,传统上,使用主设备号查找指向某些处理磁盘的内核函数(设备驱动程序)的指针。次要设备号通常用作 SCSI 总线设备号或 EIDE 设备号或类似的东西。
关于如何处理文件的其他一些决定/proc/cpuinfo是基于文件系统类型做出的。如果您执行以下操作:
% mount | grep proc
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
Run Code Online (Sandbox Code Playgroud)
您可以看到/proc文件系统类型为“proc”。从文件中读取/proc会导致内核根据文件系统的类型做不同的事情,就像在 ReiserFS 或 DOS 文件系统上打开文件会导致内核使用不同的函数来定位文件,并定位文件系统的数据。文件。
归根结底,它们都是 Unix 的文件,这就是抽象的美妙之处。
内核处理文件的方式,现在是另一回事了。
/proc 和现在的 /dev 和 /run(又名 /var/run)是 RAM 中的虚拟文件系统。/proc 是内核变量和结构的接口/窗口。
我建议阅读 Linux 内核http://tldp.org/LDP/tlk/tlk.html和 Linux 设备驱动程序,第三版https://lwn.net/Kernel/LDD3/。
我也很喜欢 FreeBSD 操作系统的设计和实现http://www.amazon.com/Design-Implementation-FreeBSD-Operating-System/dp/0321968972/ref=sr_1_1
查看与您的问题相关的相关页面。
http://www.tldp.org/LDP/tlk/dd/drivers.html
除了@RuiFRibeiro 和@BruceEdiger 的答案之外,您所做的区分并不完全是内核所做的区分。实际上,您有各种文件:常规文件、目录、符号链接、设备、套接字(我总是忘记一些,所以我不会尝试列出完整列表)。您可以通过以下方式获得有关文件类型的信息ls:它是该行的第一个字符。例如:
$ls -la /dev/sda
brw-rw---- 1 root disk 8, 0 17 nov. 08:29 /dev/sda
Run Code Online (Sandbox Code Playgroud)
开头的 'b' 表示该文件是块设备。破折号表示常规文件,“l”表示符号链接等。该信息存储在文件的元数据中stat,例如可以通过系统调用访问,因此内核可以以不同的方式读取文件和符号链接。
然后,您在“真实文件”/bin/bash和“虚拟文件”之间进行另一个区分,/proc/cpuinfo但将ls两者都报告为常规文件,因此差异是另一种类型:
ls -la /proc/cpuinfo /bin/bash
-rwxr-xr-x 1 root root 829792 24 août 10:58 /bin/bash
-r--r--r-- 1 root wheel 0 20 nov. 16:50 /proc/cpuinfo
Run Code Online (Sandbox Code Playgroud)
发生的情况是它们属于不同的文件系统。/proc是伪文件系统的挂载点,procfs而/bin/bash在常规磁盘文件系统上。当 Linux 打开一个文件时(它会根据文件系统的不同而有所不同),它会填充一个数据结构file,该数据结构除其他属性外,还有一个由多个函数指针组成的结构,用于描述如何使用该文件。因此,它可以为不同类型的文件实现不同的行为。
例如,这些是广告的操作/proc/meminfo:
static int meminfo_proc_open(struct inode *inode, struct file *file)
{
return single_open(file, meminfo_proc_show, NULL);
}
static const struct file_operations meminfo_proc_fops = {
.open = meminfo_proc_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
Run Code Online (Sandbox Code Playgroud)
如果查看 的定义meminfo_proc_open,您会发现该函数使用函数返回的信息填充内存缓冲区meminfo_proc_show,其任务是收集有关内存使用情况的数据。然后可以正常读取此信息。每次打开文件时,meminfo_proc_open都会调用该函数并刷新有关内存的信息。