• 学习笔记四


    第七章、文件操作

    一、文件操作级别

    文件操作分为五个级别,按照从低到高的顺序排列如下。

    (1) 硬件级别:硬件级别的文件操作包括:

    ·fdisk:将硬盘、U盘或SDC盘分区。

    ·mkfs:格式化磁盘分区,为系统做好准备。

    ·fsck:检查和维修系统。

    ·碎片整理:压缩文件系统中的文件。

         其中大多数是针对系统的实用程序。普通用户可能永远都不需要它们,但是它们是创建和维护系统不可缺少的工具。

    (2) 操作系统内核中的文件系统函数:每个操作系统内核均可为基本文件操作提供支持。

    (3) 系统调用:用户模式程序使用系统调用来访问内核函数。

    (4) I/O库函数:系统调用可让用户读、写多个数据块,这些数据块只是一系列字节。

    (5) 用户命令:用户可以使用Unix/Linux命令来执行文件操作,而不是编写程序。

    (6) sh脚本:虽然比系统调用方便得多,但是必须要手动输入命令,如果使用的是GUI,必须要拖放文件图标和点击指向设备来输入,操作繁琐而且耗时。

    二、文件I/O操作

        

    双线上方的上半部分表示内核空间,下半部分表示进程的用户空间。该图显示了进程读/写文件流时的操作序列。控制流用标签(1)(10)标识,说明如下。

    下面的步骤(1)~(46)是用户模式下的操作,步骤(5)~(10)是内核模式下的操作。

    (1) 用户模式下的程序执行操作可以打开一个读/写文件流。

    (2) fopen()在用户(heap)空间中创建一个FILE结构体,包含一个文件描述符fd、一个fbuf[BLKSIZE]和一些控制变量。

    (3) fread(ubuf,size,nitem,fp):nitemsize字节读取到ubuf上,通过:

    ·将数据从FILE结构体的fbuf上复制到ubuf上,通过:

    ·如果fbuf没有更多数据,则执行(4a)

    (4) 文件中的文件系统函数:

    假设非特殊文件的read(fd,fbuf[],BLKSIZE)系统调用。

    (5) read()的系统调用中,fd是一个打开的文件描述符,它是运行进程的fd数组中的一个索引,指向一个表示打开文件的OpenTable.

    (6) OpenTable包含文件的打开模式、一个指向内存中文件INODE的指针和读/写文件的当前字节偏移量。从OpenTable的偏移量,

    ·计算逻辑块编号lbk

    ·通过INODE.i_block[]数组将逻辑块编号转换为物理块编号blk

    (7) Minode包含文件的内存INDOE

    (8) 为提高磁盘I/O效率,操作系统内核通常会使用一组I/O缓冲区作为高速缓存,以减少物理I/O的数量。磁盘I/O缓冲区管理将在第12章中讨论。

    三、低级别文件操作

    1. 分区

    一个块存储设备,如硬盘、U盘、SD卡等,可以分为几个逻辑单元,称为分区。各分区均可以格式化为特定的文件系统,也可以安装在不同的操作系统上。大多数引导程序,如GRUBLILO等,都可以配置为从不同的分区引导不同的操作系统。分区表位于第一个扇区的字节偏移446(0xlBE)处,该扇区称为设备的主引导记录。

    每个拓展分区的第一个扇区是一个本地MBR。每个本地MBR在字节偏移量0X1BE处也有一个分区表,只包含两个条目。第一个条目定义了拓展分区的起始扇区和大小。第二个条目指向下一个本地MBR。所有本地MBR的扇区编号都与P4的起始扇区有关。

    1. 格式化分区

    fdisk只是将一个存储设备划分为多个分区.每个分区都有特定的文件系统类型,但是分区还不能使用。为了存储文件,必须先为特定的文件系统准备好分区。该操作系统习惯上称为格式化磁盘或磁盘分区。

    1. 挂载分区

    Man 8 losetup:显示用于系统管理的losetup实用工具命令:

    (1) dd命令创建一个虚拟磁盘映像

    (2) vdisk上运行fdisk来创建一个分区P1

    (3) 使用以下扇区数在vdisk的分区1上创建一个循环设备

    (4) 格式化/dev/loop1,它是一个EXT2文件系统

    (5) 挂载循环设备

    (6) 访问作为文件系统一部分的挂载设备

    (7) 设备使用完毕后,将其卸载

    (8) 循环设备使用完毕后,通过以下命令将其断开

    四、EXT2文件系统简介

    1. EXT2文件系统数据结构

    Linux下,我们可以创建一个包含简单EXT2文件系统的虚拟磁盘,如下文所示。

    1. 超级快

    Block#1:超级块(在硬盘分区中字节偏量为1024B1是超级块,用于容纳关于整个文件系统的信息。下文说明了超级块结构中的一些重要字段。

    1. 块组描述符

    Block#2:块组描述符块(硬盘上的s_first_data_blocks-1)EXT2将磁盘块分成几个组。每个组有8192个块。每组用一个块组描述符结构体描述。

    1. 位图

    Block#8:块位图

    Block#9:索引节点位图

    1. 索引节点

    Block#10:索引(开始)节点块

    每个文件都用一个128字节(EXT4中的是256字节)的独特索引节点结构体表示。下面列出了主要索引节点字段。

    直接块、间接块、双重间接块、三重间接块

    数据块:紧跟在索引节点块后面的是文件存储块。

    1. 目录条目

    EXT2目录条目:目录包括dir_entry结构。

    第八章、使用系统调用进行文件操作

    一、系统调用

    二、系统调用手册页

    三、使用系统调用进行文件操作

    系统调用必须由程序发出。它们的用法就像普通函数调用一样。每个系统调用都是一个库函数,它汇集系统调用函数,并最终向操作系统内核发出一个系统调用。

    四、常用的系统调用

    五、链接文件

    1. 硬链接文件                                                                                                                                                                                                                                                                                                           硬链接:命令       ln oldpath newpath 创建从newpath到oldpath的硬链接。对应的系统调用为:link(char *oldpath, char *newpath)                                                                                                                     硬链接文件会共享文件系统中相同的文件表示数据结构(索引节点)。文件链接数会记录链接到同一索引节点的硬链接数量。硬链接仅适用于非目录文件。否则,它可能会在文件系统名称空间中创建循环,这是不允许的。相反,系统调用: unlink(char  *pathname)会减少文件的链接数。如果链接数变为0,文件会被完全删除。这就是rm(file)命令的作用。如果某个文件包含非常重要的信息,就最好创建多个链接到文件的硬链接,以防被意外删除。

    软链接:命令

    ln -s oldpath newpath 

    创建从newpath到oldpath的软链接或符号链接。对应的系统调用是:

    symlink(char *oldpath, char *newpath)

    newpath是LNK类型的普通文件,包含oldpath字符串。它可作为一个绕行标志,使访问指向链接好的目标文件。与硬链接不同,软链接适用于任何文件,包括目录。

    六、stat系统调用

    #include <sys/ types.h>

    #include <sys/stat.h>

    #include <unistd.h>

    int stat (const char *file_name,struct stat *buf);

    int fstat (int filedes,struct stat *buf) ;

    int lstat(const char *file_name,struct stat *buf) ;

    1. stat文件状态
    2. stat结构体
    3. stat与文件索引节点                                                                                                       struct ext2_inode{                                                                                                         u16 i_mode;                                                                                                           u16 i_uid;                                                                                                           u32 i_size;                                                                                                           u32 i_atime;                                                                                                           u32 i_ctime;                                                                                                           u32 i_mtime;                                                                                                           u32 i_dtime;                                                                                                           u16 i_gid;                                                                                                       u16 i_links_count;                                                                                                     u32 i_blocks;                                                                                                         u32 i_flags;                                                                                                           u32 i_reservedl;                                                                                                       u32 i_blocks[15];                                                                                                       u32 pad[7];                                                                                                           };//inode=128 bytes in ext2/3 FS; 256 bytes in ext4                                                                                 每个索引节点在存储设备上都有唯一的索引节点编号(ino)。                                     
    4. 文件类型和权限
    5. opendir-readdir函数
    6. readlink函数                                                                                                        linux的open()系统调用遵循符号链接。因此,无法打开符号链接文件并读取其内容。要想读取符号链接文件的内容,我们必须使用readlink系统调用,即
      int readlink(char *pathname,char buf[],int bufsize)
      他将符号链接文件的内容复制到bufsize的buf[]中,并将实际复制的字节数返回。
    7. ls程序
    8. open-close-lseek系统调用
    9. 打开文件和文件描述符
    10. 关闭文件描述符
    11. lseek文件描述符
    12. write()系统调用

    七、文件操作示例程序

           1.显示文件内容

           2.复制文件

           3.选择性文件复制

     八、编程项目:使用系统调用递归复制文件

  • 相关阅读:
    《硅谷之谜》读书笔记
    Google的Bigtable学习笔记(不保证正确性)
    软件开发到底是怎么一回事呢?
    如何控制自己之2016个人目标管理
    如何自适应网页的协议(http/https/……)
    数据库时间戳设计
    AngularJS-Controller的使用-读书笔记
    FIM相关报错汇总
    iPad上的Cookie到底有多长?
    【solr】join查询,跟mysql的join不一样
  • 原文地址:https://www.cnblogs.com/lxhs/p/15391119.html
Copyright © 2020-2023  润新知