新建设电影院+网站,中国房产网,centos wordpress install,石家庄做外贸的网站第四章 文件管理
9.文件基本操作 “打开文件和关闭文件”与平常鼠标双击打开文件和点击“X”关闭文件是有所不同的。
操作系统在处理open系统调用时主要做了以下两件事情#xff0c;①根据我们提供的文件存放路径在外存当中找到这个目录对应的目录表#x…第四章 文件管理
9.文件基本操作 “打开文件和关闭文件”与平常鼠标双击打开文件和点击“X”关闭文件是有所不同的。
操作系统在处理open系统调用时主要做了以下两件事情①根据我们提供的文件存放路径在外存当中找到这个目录对应的目录表另外不同的用户对文件的操作权限是不一样的有的用户可能只可以读这个文件而有的用户既可以读文件也可以写文件而这些用户对文件的访问权限信息(访问控制列表ACL)其实也是记录在目录项当中的所以可以根据目录项来检查此时用户请求的这个操作到底是否合法如果用户没有这种操作权限的话就可以拒绝用户打开文件而如果用户有这种操作权限的话那么接下来操作系统会把这个文件对应的目录项复制到内存中的“打开文件表”中也就是说在用户打开了一个文件之后这个文件相关的信息就已经放到内存当中了之后用户想要再操作这个文件只需要根据这个“打开文件表”的编号就可以找到自己想要操作的这个文件的一切信息这样的话就不需要每次查文件的时候都重新访问目录了因此把目录项复制到打开文件表当中是可以大幅度的提升文件访问的速度的。
需要注意的是有两种打开文件表一种是系统的打开文件表整个系统只有一张这个打开文件表中会记录所有的正在被其他进程使用的文件的一些信息。另外每个进程也会有自己的打开文件表这张表中记录了自己的这个进程此时已经打开的文件是哪些在进程的打开文件表中会有一个系统表的索引号比如“test.txt”这个文件在系统打开文件表中是编号k这个表项那么进程打开文件表会记录下这个编号k同样的如果另一个进程B也打开了“test.txt”这个文件那它同样也会指向系统的打开文件表。在系统的打开文件表中有一个字段“打开计数器”用来记录这个文件此时已经被几个进程打开了此时如果有两个进程打开了这个文件的话那这个打开计数器就应该修改为2。“打开计数器”这个字段是系统打开文件表中所特有的一个字段。
在整个系统当中设置一个打开文件表的总表即系统打开文件表是比较方便实现某一些文件管理功能的。比如说在使用Windows操作系统的时候如果我们要尝试删除某一个txt文件那此时如果这个txt文件已经被某个记事本进程打开了那么系统是会提示我们暂时无法删除该文件其实系统在背后做的事情就是当我们选择删除文件的时候它首先来检查这个文件是否已经被某个进程打开了也就是查询了系统当中的打开文件表如果此时这个文件正在被某个进程使用的话那么这个文件的数据显然是暂时不能删除的所以如果我们在系统当中设置了一个系统打开文件表这样的总表那么对于一些文件管理的功能是很方便实现的。另外在进程的打开文件表当中会有一个字段“读写指针”记录了这个进程对文件进行读写操作此时进行到了什么位置。在进程的打开文件表中还需要标明这个进程对文件的访问权限。比如说进程A在打开test.txt这个文件的时候只是声明了自己只会对test.txt这个文件进行“只读”操作那么如果这个进程在之后尝试对这个文件进行“写操作”那操作系统会检查它之前申请的访问的类型由于之前它只是声明了“只读”所以这个写操作应该拒绝。在进程打开文件表中比较特殊的是“读写指针”和“访问权限”这两个字段不同的进程对一个文件进行读写操作进行到的位置是不一样的所以不同进程的读写指针也是应该不一样另外不同的进程在打开一个文件的时候所申请的这种访问类型也是不一样的因此访问权限这个字段也应该放在进程的打开文件表中。当然除了这里列出的字段之外在进程的打开文件表中还会有其他的一些文件的信息这里没有全部列举。 用户使用完一个文件要“关闭文件” 当这个进程选择关闭一个文件的时候那么可以把这个进程的打开文件表中这个文件对应的表项删除相应的需要回收分配给这个文件内存缓冲区等等一系列的资源。另外需要对系统打开文件表中对应表项的打开计数器进行-1操作由于此时这个打开计数器依然是0的所以说明此时这个文件还在被其中的某一些进程所使用因此系统打开文件表中对应的表项暂时还不能删除只有打开计数器为0的时候才需要删除系统打开文件表中的表项。 读文件、read系统调用 在我们双击打开test.txt这个文本文档的时候在背后其实是调用了操作系统提供的read系统调用也就是读文件的功能。通过之前的讲解可以知道在对文件进行读写操作之前一定要先打开文件所以其实在正式开始读文件的时候“记事本”这个进程的打开文件表当中已经有了这个文件对应的表项了因此记事本这个进程在读文件的时候只需要指明自己要读的这个文件它对应的打开文件表中的编号到底是多少就可以了。这就是读文件的时候需要提供的第一个参数就是要指明到底要读的是哪一个文件。第二个在读文件的时候还需要指明此时需要读入多少数据另外还要指明这个读入的数据是存放在内存中的什么位置。这些参数的填充都是“记事本”这个进程在背后为我们完成的事情。 操作系统在处理read系统调用的时候会根据打开文件表中读写指针这个读指针所指向的外存地址那个地方读入用户指定的大小的这么多数据然后放入到用户指定的内存区域当中。 写文件和读文件是很类似的在编辑完一个文本文档之后我们可以点击文件保存点击保存之后其实记事本这个应用程序在背后是帮我们调用了操作系统提供的写文件功能即write系统调用这个系统调用的作用就是把这个文件在内存当中的数据再写回到外存保存到外存当中。所以在进行write系统调用的时候我们也需要提供这样的几个参数第一需要指明要写的是哪个文件同样的这个进程只需要指明这个文件在打开文件表中的编号是多少操作系统就知道要写的是哪个文件了。另外还需要指明这个写操作需要写回的数据大小到底是多少另外还需要指明要写回外存的这些数据是放在内存当中的什么位置的。 操作系统根据write系统调用的参数会从用户指定的内存区域中读出指定大小的数据然后写回“写指针”所指向的外存区域当中。 总结 最重要的是打开文件该操作会把目录项的信息复制到内存当中的打开文件表中需要知道内存当中有两种打开文件表一种是系统的打开文件表整个系统只有一张另外一种是进程打开文件表。系统的打开文件表中包含了所有的正在被使用的文件信息而进程的打开文件表中只包含了这个进程本身打开了的那些文件信息。
需要注意的是在打开文件的时候并不会把文件的数据直接读入内存只是把文件的目录项给复制到了内存的打开文件表当中。另外系统会把打开文件表当中的索引号返回给用户之后用户就可以根据这个索引号来查询打开文件表然后直接操作自己的文件而不用再每一次都查询目录这个地方的索引号在有的教材上也称为“文件描述符”这个术语在真题中出现过。所以“文件描述符”这个术语也需要注意一下它指的其实就是进程的打开文件表中的编号。 另外需要注意在进程的打开文件表和系统的打开文件表中都会有一些各自特有的属性比如每个进程都不一样的读写指针和访问权限这些肯定需要放在进程的打开文件表中的而一个文件总共被多少个进程打开了这个数据肯定是需要放在系统的打开文件表中。 比较容易和打开文件混淆的是读文件这个操作只有读文件的时候才会把文件的数据真正的从外存读入内存。 而对文件进行读写操作的时候用户不需要再提供文件名文件路径这些信息只需要提供“文件描述符”也就是这个文件在打开文件表当中的索引号操作系统就可以知道要读写的是哪个文件了。