第七章 文件操作
第七章的主要内容是文件操作,主要包括以下几个方面:
- 文件操作级别
- 文件I/O操作
- 低级别文件操作
- EXT2文件系统简介
一、知识点归纳以及自己最有收获的内容
1.文件操作级别
- 硬件级别(创建和维护系统不可少的工具):
fdisk:将盘进行分区。
mkfs:格式化磁盘分区。
fsck:检查系统。
碎片整理:压缩文件系统中的文件 - 操作系统内核中的文件系统函数
操作系统内核可为文件操作提供支持。 - 系统调用:用户模式程序使用系统调用来访问内核函数
open(),read(),lseek()和close()都是c语言库函数。每个库函数都会发出一个系统调用,使进程进入内核模式来执行相应的内核函数,当进程结束执行内核函数使,会返回到用户模式,并得到所需的结果。 - I/O库函数
用户通常需要读/写单独的字符、行或数据结构记录等。I/O库函数建立在系统调用之上,提高了运行效率。 - 用户命令:用户可以使用Unix/Linux命令来执行文件操作,而不是编写程序。
- sh脚本:虽然比系统调用方便的多,但是必须要手动呼入命令,如果使用的是GUI,必须要拖放文件图标和点击指向设备来输入,操作繁琐而且耗时。
2.文件I/O操作
(1)用户模式下的程序执行操作
FILE *p = fopen("file", "r"); or FILE *p = fopen( "file", "w");
可以打开一个读/写文件流。
(2) fopen()在用户(heap)空间中创建一个FILE结构体,包含一个文件描述符fd、一个fbuf[BLKSIZE]和一些控制变量。它会向内核中的kopen()发出一个
fd =open("file",flags=READ or WRITE)系统调用,构建一个OpenTable来表示打开文件示例。OpenTable的mptr指向内存中的文件INODE。对于非特殊文件,INODE 的i_block数组指向存储设备上的数据块。成功后,fp会指向FILE结构体,其中fd是open()系统调用返回的文件描述符。
(3) fread(ubuf, size,nitem, fp):将nitem个size字节读取到ubuf上,通过:
- 将数据从FILE结构体的fbuf上复制到ubuf上,若数据足够、则返回。
- 如果fbuf没有更多数据,则执行(4a)。
(4a)发出read(fd, fbuf, BLKSIZE)系统调用,将文件数据块从内核读取到fbuf上,然后将数据复制到ubuf上,直到数据足够或者文件无更多数据可复制。
(4b)fwrite(ubuf, size, nitem, fp):将数据从ubuf复制到 fbuf。
- 若(fbuf有空间):将数据复制到fbuf上,并返回。
- 若(fbuf已满):发出 write(fd, fbuf, BLKSIZE)系统调用,将数据块写入内核,然后再次写入fbuf。
这样,fread()/fwrite()会向内核发出read(/write)系统调用,但仅在必要时发出,而且它们会以块集大小来传输数据,提高效率。同样,其他库I/O函数,如 fgetc /fputc、fgets/fputs、fscanf/fprintf等也可以在用户空间内的FILE结构体中对fbuf进行操作。
(5)内核中的文件系统函数:
假设非特殊文件的read(fd, fbuf[], BLKSIZE)系统调用。
(6)在read()系统调用中,fd是一个打开的文件描述符,它是运行进程的fd数组中的一个索引,指向一个表示打开文件的 OpenTable。
(7)OpenTable包含文件的打开模式、一个指向内存中文件 INODE的指针和读/写文件的当前字节偏移量。从OpenTable的偏移量,
- 计算逻辑块编号lbk。
- 通过 INODE.i_block[]数组将逻辑块编号转换为物理块编号blk 。
(8)Minode包含文件的内存INODE。EMODE.i_block[]数组包含指向物理磁盘块的指针。文件系统可使用物理块编号从磁盘块直接读取数据或将数据直接写入磁盘块,但将会导致过多的物理磁盘I/O。
(9)为提高磁盘VO效率,操作系统内核通常会使用一组I/O缓冲区作为高速缓存,以减少物理I/O的数量。
(9a)对于read(fd, buf, BLKSIZE)系统调用,要确定所需的(dev, blk)编号,然后查询I/O缓冲区高速缓存,以执行以下操作:
.get a buffer = (dev, blk); .if (buffer's data are invalid){ start_io on buffer; wait for I/O completion; } .copy data from buffer to fbuf; .release buffer to buffer cache;
(9b)对于write(fd, fbuf, BLKSIZE)系统调用,要确定需要的(dev, blk)编号,然后查询IO缓冲区高速缓存,以执行以下操作:
(10)设备I/O:I/O缓冲区上的物理I/O最终会仔细检查设备驱动程序,设备驱动程序
由上半部分的start_io()和下半部分的磁盘中断处理程序组成。
3.低级别文件操作
- 分区
- 一个区块存储设备可以分为几个逻辑单元,称为分区。
- 分区表位于第一个扇区的字节偏移446(ox1BE)处,改扇区称为设备的主引导记录。
- 如果某分区是扩展类型(类型编号=5),那么它可以划分为更多分区。假设分区P4是扩展类型,它被划分为扩展分区P5、P6、P7。扩展分区在扩展分区区域内形成一个链表。
- 每个扩展分区的第一个扇区是一个本地MBR。每个本地MBR在字节偏移量0xIBE处也有一个分区表,只包含两个条目。第一个条目定义了扩展分区的起始扇区和大小。第二个条目指向下一个本地MBR。所有本地MBR的扇区编号都与P4的起始扇区有关。照例,链表以最后一个本地MBR中的0结尾。在分区表中,CHS值仅对小于8GB的磁盘有效。对大于8GB但小于4G扇区的磁盘,只有最后两个条目start _sector 和nr sector有意义。
- 格式化分区:
fdisk只是将一个存储设备划分为多个分区。每个分区都有特定的文件系统类型,但是分区还不能使用。为了存储文件,必须先为特定的文件系统准备好分区。该操作习惯上称为格式化磁盘或磁盘分区。
- 挂载分区:
man 8 losetup:显示用于系统管理的losetup实用工具命令。
4.EXT2文件系统
EX2文件系统数据结构
- Block#0:引导块—容纳从磁盘应道操作系统的引导程序。
- Block#1:超级块—用于容纳关于整个文件系统的信息。
- Block#2:块组描述符块—EXT2将磁盘块分成几个组,每组由8192个块,每组用一个块组描述符结构体描述。
- Block#8:块位图—表示磁盘块或者索引节点的位序列,用于分配和回收项。
- Block#10:索引(开始)节点块
第八章 使用系统调用进行文件操作
一、知识点归纳以及自己最有收获的内容
-
系统调用
在操作系统中,进程以两种不同的模式运行,即内核模式和用户模式,简称Kmode和Umode。在Umode中,进程的权限非常有限。它不能执行任何需要特殊权限的操作。特殊权限的操作必须在Kmode下执行。系统调用(简称syscall)是一种允许进程进入Kmode以执行Umode不允许操作的机制。复刻子进程、修改执行映像,甚至是终止等操作都必须在内核中执行。
-
使用系统调用进行文件操作
- access:检査对某个文件的权限
int access(char •pathname, int mode);
- chdir:更改目录
int chdir(const char *path);
- chmod:更改某个文件的权限
int chmod(char *path, mode_t mode);
- chown:更改文件所有人
int chown(char *name, int uid, int gid);
- chroot:将(逻辑)根目录更改为路径名
int chroot (char *patiiname);
- getcwd:获取CWD的绝对路径名
char *getcwd(char *buf, int size);
- mkdir:创建目录
int mkdir(char *pathname, mode_t mode);
- rmdir:移除目录(必须为空)
int rmdir (char *pathname);
- link:将新文件名硬链接到旧文件名
int link(char *oldpath, char *newpath);
- unlink:减少文件的链接数;如果链接数达到0,则删除文件
int uniink(char *pathname);
- symlink:为文件创建一个符号链接
int symliak(char *oldpath, char *newpath);
- rename:更改文件名称
int rename(char *oldpath, char *newpath);
- utime:更改文件的访问和修改时间
int utime(char *pathname, struct utimebuf *time)
- 以下系统调用需要超级用户权限:
- mount:将文件系统添加到挂载点目录上
int mount(char *specialfile, char *mountDir);
- umount:分离挂载的文件系统
int umount(char *dir);
- mknod:创建特殊文件
int mknod(char *path, int mode, int device);
- access:检査对某个文件的权限
-
常用的系统调用
- stat:获取文件状态信息
int stat(char *filename, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(char *filename, struct stat *buf);
- open:打开一个文件进行读、写、追加
int open(char *file, int flags, int mode);
- close:关闭打开的文件描述符
int close(int fd);
- read:读取打开的文件描述符
int read(int fd, char buf[], int count);
- write:写入打开的文件描述符
int write(int fd, char buf[], int count);
- lseek:重新定位文件描述符的读/写偏移量
int lseek(int fd, int offset, int whence);
- dup:将文件描述符复制到可用的最小描述符编号中
int dup(int oldfd);
- dup2:将oldfd复制到newfd中,如果文件链接数为0,则删除文件
int dup2(int oldfd, int newfd);
- link:将新文件硬链接到旧文件
int link(char *oldPath, char *newPath);
- unlink:取消某个文件的链接;如果文件链接数为0,则删除文件
int unlink(char *pathname);
- symlink:创建一个符号链接
int symlink(char *target, char *newpath);
- readlink:读取符号链接文件的内容
int readlink(char *path, char *buf, int bufsize);
- umask:设置文件创建掩码;文件权限为(mask & ~umask)
int umask(int umask);
二、问题及解决情况
问题:链接文件的详细阐述以及两种链接文件的区别是什么
1,软链接可以理解成快捷方式。它和windows下的快捷方式的作用是一样的。
2,硬链接等于cp -p 加 同步更新。
区别:软链接文件的大小和创建时间和源文件不同。软链接文件只是维持了从软链接到源文件的指向关系(从jys.soft->jys可以看出),不是源文件的内容,大小不一样容易理解。
硬链接文件和源文件的大小和创建时间一样。硬链接文件的内容和源文件的内容一模一样,相当于copy了一份。
- 软链接:
以路径形式存在,类似于快捷方式
可以跨文件系统
可以对一个不存在的文件名进行链接
可以对目录进行链接
- 硬链接:
以文件副本形式存在,但不占用实际空间
不允许给目录创建硬链接
只能在同一个文件系统中才能创建
三、代码实践
使用系统调用进行文件操作 mkdir,chdir,getcwd系统调用
标签:文件,八章,第七,int,fbuf,笔记,char,调用,链接 From: https://www.cnblogs.com/MRC-/p/16728703.html