day03

随机读写:
    每个打开的文件都有一个记录读写位置的指针,也称文件位置指针,对文件的读写时该指针会自动往后移动,因此顺序读写时无需操作
    当需要去文件的任意位置进行读写时,才需要调整该指针的位置
    标准IO:
        int fseek(FILE *stream, long offset, int whence);
        返回值:成功返回0,失败返回-1
    系统IO:
        off_t lseek(int fd, off_t offset, int whence);
        返回值:成功返回调整后位置指针的位置,失败返回-1

系统IO中的文本文件的读写:
    在系统IO中没有类似fprintf/fscanf函数,因此没有直接对文本文件读写的操作
    但是可以通过把数据转换成字符串进行间接的文本文件读写
    写文本文件
        任意类型数据对象通过 sprintf 转换成字符串 write写入
    读文本文件
        按字符串格式读取到内存 sscanf 解析到各种任意类型数据中

文件描述符:
    1、非负整数,代表了一个打开的文件
    2、通过系统调用(open/creat)返回,该数值是被内核使用的
    3、它在内核中对应一个内核对象,因为内核不能暴露它真实的地址,因此不能直接返回真实的文件地址,而是使用文件描述符来表示
    4、内核中有一张记录了所有已打开的文件的二维表,文件描述符就是访问该表的每行的下标,文件描述符也成为句柄,就是访问文件的凭证
    5、内核中有三个默认长期打开的文件描述符
        0:标准输入     STDIN_FILENO      FILE* stdin
        1:标准输出     STDOUT_FILENO     FILE* stdout
        2:标准错误     STDERR_FILENO     FILE* stderr

文件描述符重定向:
    int dup(int oldfd);
    功能:复制一个已经打开的文件描述符
    返回值:返回一个当前进程没有使用的最小文件描述符,该描述符与oldfd对应一个文件(两个文件描述符都是同一个文件)

    int dup2(int oldfd, int newfd);
    功能:复制oldfd文件描述符为newfd
        如果newfd已经被打开,那么会先关闭newfd,再复制(两个文件描述符都是同一个文件)

    重定向的作用:
        通过把一个已经打开的文件描述符fd,经过dup2指定复制为标准输入0/标准输出1/标准错误2,则会先关闭已经打开的0/1/2,然后同时对应fd,就可以通过printf/scanf函数就可以直接往fd对应的文件进行读写,相当于使用了write/read
        但是在当前进程中后序无法使用标准输入、输出、错误文件,因此可以在开始前通过dup先备份这些文件,结束后通过dup2重新指向标准文件

文件同步:
    1、在写入数据时,内存与磁盘之间有一块缓冲区,目的是为了降低磁盘的读写次数、调高读写效率
    2、但是这种机制带来的后果是磁盘中的数据与实际写入的数据可能不符,系统提供三个函数让缓冲区中的数据立即写入磁盘,称为文件同步
        fsync/sync/fdataync

文件属性:
    int stat(const char *pathname, struct stat *buf);
    功能:根据文件路径来获取文件的属性
        buf:输出型参数
    int fstat(int fd, struct stat *buf);
    功能:根据文件描述符获取文件的属性

    int lstat(const char *pathname, struct stat *buf);
    功能:根据文件路径获取软链接文件的属性

    struct stat
    {
        dev_t     st_dev;         /* 设备ID */
        ino_t     st_ino;         /* inode节点号 */
        mode_t    st_mode;        /* 文件的类型和权限 */
        nlink_t   st_nlink;       /* 硬链接数 */
        uid_t     st_uid;         /* 用户ID */
        gid_t     st_gid;         /* 组ID */
        dev_t     st_rdev;        /* 特殊文件设备ID */
        off_t     st_size;        /* 文件总字节数,以字节为单位 */
        blksize_t st_blksize;     /* IO块总字节数 */
        blkcnt_t  st_blocks;      /* 占用大小512字节内存块的数量 */

               /* Since Linux 2.6, the kernel supports nanosecond
                  precision for the following timestamp fields.
                  For the details before Linux 2.6, see NOTES. */

        struct timespec st_atim;  /* 最后访问时间 */
        struct timespec st_mtim;  /* 最后修改时间 */
        struct timespec st_ctim;  /* 最后状态的修改时间 */

        #define st_atime st_atim.tv_sec      /* Backward compatibility */
        #define st_mtime st_mtim.tv_sec
        #define st_ctime st_ctim.tv_sec
    };

文件的权限:
    int access(const char* pathname,int mode)
    功能:测试当前用户对文件的权限
        pathname:想要测试的文件路径
        mode:想要测试的权限
            F_OK    测试文件是否存在
            R_OK    测试文件是否有读权限
            W_OK    测试文件是否有写权限
            X_OK    测试文件是否有执行权限
    返回值:存在返回0,不存在返回-1
    int chmod(const char *pathname, mode_t mode);
    功能:根据文件路径修改文件权限
        mod:由三个八进制数组成的权限掩码
            0xxx
            0644    0666    普通文件
            0755    0777    可执行文件
    int fchmod(int fd, mode_t mode);
    功能:根据文件描述符修改文件权限

    权限屏蔽码:
        如果想让新创建(open、creat)的文件不具备某些权限,可以通过设置权限屏蔽码进行屏蔽权限
        查看命令 umask 查看当前终端的权限屏蔽码
        注意:可以通过chmod命令、函数可以无视权限屏蔽码,
        修改权限屏蔽码:
            命令:umask 0xxx 修改成0xxx
            注意:只是当时终端临时有效,如果想要长期有效需要修改配置文件
            函数:mode_t umask(mode_t mask);
                mask:新的屏蔽码
                返回值:原来的屏蔽码
            注意:该函数只是进程中生效,进程结束后就失效

修改文件的大小:
    int truncate(const char *path, off_t length);
    功能: 根据文件路径截取文件长度
        length:截取后文件的长度(字节)

    int ftruncate(int fd, off_t length);
    功能:根据文件描述符截取文件长度

文件删除、重命名:
    int remove(const char* pathname);
    功能:由c标准库提供的删除文件函数

    int unlink(const char *pathname);
    功能:操作系统提供的删除文件函数
        remove底层调用unlink、rmdir函数
        1、如果删除的是硬链接文件或者源文件本身且文件本身是关闭的,则是把该文件的硬连接数-1,如何清除该文件的inode信息,block不清理
        2、当文件的硬连接数减到0时,系统就把该文件的block权限释放,可以用于存储其他文件的数据
        3、如果删除软链接文件,则删除的是软链接文件的inode信息,而不会删除源文件的数据,没有任何一个函数可以通过软链接文件删除源文件
   
    int rename(const char* oldpath,const char *newname);
    功能:重命名文件

什么是软链接文件:
    Linux文件系统会把分区分为两大部分:
    inode信息块区:
        每块默认128B,记录某个文件的文件权限、大小、所有者、修改时间等属性信息以及该文件的block信息,每个文件有且只有一个inode信息块

    block数据块区:
        每块默认4Kb,记录了文件的真正内容数据、文件名
    每个文件有且只有一个inode信息块以及若干个block数据块,读取文件file需要借助所在目录文件的block中记录的file文件的inode号和文件名,来找到file的inode的信息块,从而读取file文件的block数据块

    硬链接文件:
        没有属于自己的inode和block,只是在不同的目录下复制链接的源文件的inode信息块,通过该复制的inode信息块访问源文件的block数据块
    软链接文件:
        软链接文件会创建自己的新的inode和block块,在软链接的block中不存储源文件的数据,而是存储源文件的inode信息号,从而借助源文件的inode来访问源文件的block
    区别:
        1、删除源文件,只是删除源文件的inode信息块中的数据(指向block的箭头),block的数据不会清理,所以硬链接依然可以访问,但是软链接文件就无法访问
        2、当文件的硬连接数删除到0时,文件才算被真正删除了
        3、修改硬链接文件的内容,源文件也会随之修改,软链接不会
        4、硬链接不能连接目录、软链接可以
        5、硬链接不能跨文件系统、软链接可以
    int link(const char* oldpath,const char *newname);
    功能:创建硬链接文件

    int symlink(const char *target,const char *linkpath);
    功能:创建软链接文件 文件类型 l

目录操作:
    int mkdir(const cahr *pathname,mode_t mode)
    功能:创建空目录
        mode:目录的权限必须有执行权限才能进入目录
    返回值:成功0 失败-1

    int rmdir(const char *pathname)
    功能:删除空目录
   
    int chdir(const char *pathname)
    功能:修改当前的工作路径为path  相当于命令cd

    char *getcwd(char *buf,size_t size)
    功能:获取当前进程的工作路径    相当于命令pwd

    DIR *opendir(const char *name);
    功能:根据目录路径打开目录
    返回值:成功返回一个目录流对象
    DIR *fdopendir(int fd);
    功能:根据目录文件描述符打开目录
    返回值:成功返回一个目录流对象

    注意:DIR目录流对象记录了该目录中所有文件的信息
    struct dirent *readdir(DIR *dirp);
    功能:从目录流dirp中读取一条文件信息并返回
    struct dirent {
        ino_t          d_ino;       /* inode number */
        off_t          d_off;       /* 距离下一条信息的字节数 */
        unsigned short d_reclen;    /* 当前信息的字节数 */
        unsigned char  d_type;      /* 文件类型 */
        char           d_name[256]; /* filename */
    };
    注意:readdir读取完一条信息后,会自动的指向下一条信息,只需要继续执行readdir即可读取下一条,直到返回值为NULL时读取完毕
posted @ 2023-08-17 19:16  歪爱慕外  阅读(17)  评论(0)    收藏  举报