zoukankan      html  css  js  c++  java
  • [POSIX]文件系统(概述)

    1.文件名由除系统目录分隔符(unix是/,windows是)和空字符“”外的任意ASCII字符组成,现代系统很多还可以包含UNICODE字符,但是还是推荐使用传统的ASCII码命名.

    2.目录不能创建硬链接.

    3.文件描述符是一个非负数.

    4.文件描述符(fd)是一个非负数,每个进程的fd之间不存在联系,每个进程都有一个注1|进程表项,每个进程调用打开文件系统调用时,进程表项就会增加一条,每条的id就是fd,fd只会按照“从0开始(每个进程从各自的0开始),返回最小的未用的fd”的这个规则返回fd(通常0到2会被系统标准输出输入占用),不同进程打开同一个文件,会有不同的fd返回.

    5.一般shell程序会把0、1、2三个文件描述符标准化为shell程序的输入输出和错误输出,换句话说文件描述符0到2已经被这3个标准输入输出占用了.

    POSIX也定义了三个常量代表了这三个数字包含在unistd.h头文件上

    STDIN_FILENO 0
    STDOUT_FILENO 1
    STDERR_FILENO 2

    代码示例:

    #include <fcntl.h>
    #include <unistd.h>
    
    int main(void){
        char s_1[] = "my error.
    ";
        write(STDERR_FILENO, s_1, 10);
        return 0;
    }

    此代码片段会在控制台,输出"my error. ".

    6.在shell中启动的进程写入STDOUT_FILENO和STDERR_FILENO会输出到屏幕,但是STDOUT_FILENO是带缓冲的IO,而STDERR_FILENO是即刻响应的.

    7.由open和openat返回的文件描述符,一定是最小未用的文件描述符,利用这一特性,应用程序可以关闭掉标准的输入输出从而启动自行的输入输出.

    代码示例:

    #include <fcntl.h>
    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main(void){
        #define LEN 3
        char p_1[] = "./abc.txt";
        close(STDOUT_FILENO);
        int fd_1 = open(p_1, O_RDWR|O_APPEND|O_CREAT);
        
        printf("%d
    ", fd_1);
    
        return 0;
    }

    以上代码关闭了标准输出,再把它重定向到了进程当前工作目录下的"./abc.txt"文件,这时进程的所有输出,都会被记录到"./abc.txt"上.

     8.具有缓冲的I/O,当输入或输出还不至于填满缓冲区时,实际只是I/O到缓冲区,只有在两种情况带缓冲的函数才会输出到设备:

         ---缓冲区被填满,缓冲区内容自动被刷出.

         ---程序正确退出(exit(0)),就算缓冲区不被填满也会被刷出.

     9.在shell终端,当键入回车键时终端进程实际上会执行两个动作.

        ---输入当前系统回车字符,至于输入什么字符通常是终端运行系统环境决定的,Unix体系为 ,Windows体系为 .

        ---发送输入内容,也就是把输入内容写进STDIN.

    10.一些带缓冲的,操作字符串的I/O函数,会在读取的返回内容长度n的位置自动填充,所以它读取的字符长度实际上只有n-1,例如fgets.

    11.一些带缓冲的,操作字符串的I/O函数,在每次调用的时候会自动刷出缓冲区,就像调用fflush(fd)一样,例如fgets.

    13.事实上,就算是不带缓冲的I/O函数,如read,write,也不会直接操作存储设备,传统unix系统实现在内核中设有缓冲区高速缓存或页高速缓存,大多数磁盘I/O都是通过缓冲区进行.举个例子,当进程A向文件A写入一个字符,内核并不会马上启动硬件把这一个字节写入存储设备,而是先填充在高速缓冲区,当进程B恰好向文件A读取此字符,内核会在缓冲区返回这个字符,同时会刷新缓冲区,这些操作,对于应用程序本身是感知不到的,除非你把存储设备同时绑定两个系统,如虚拟机和宿主共同访问一个存储设备,你会发现这个细节。

    14.Unix还提供了一些函数来操作I/O高速缓存,通常还有一个守护进程定时将缓冲区的内容刷出缓冲区,详情请参考《Unix高级环境编程》3.13 函数sync、fsync和fdatasync.

    15.当open/openat以O_APPEND标志打开文件时,调用lseek将不能改变write的偏移位,此时write的偏移位始终会在结尾开始,但是可以改变read的偏移位.

    16.当文件不支持lseek时,可以调用lseek(STDIN_FILENO, 0, SEEK_CUR) == -1来判断,切忌一定要看是否等于-1,判断小于0没用,因为有些系统lseek支持设置为负值.

    17.lseek仅将当前的文件偏移量记录在内核中,它并不引起任何I/O操作,因此在打开一个空文件,并设置偏移位,并不会为该文件写入任何东西,直到真正调用写入操作为止.

    18.O_APPEND具有一定的特殊性,调用操作偏移位函数对write无效的根本原因是,每次write都会从v(i)-node获取文件长度作为自己的偏移量的特性,这就意味着你不能用无O_APPEND标志的fd设置一个跟文件长度对等的偏移位去模拟O_APPEND的行为.

    19.当存在多个进程打开同一个文件,那么每个进程的这个fd会各自维护一个注2|文件表项,这个表包括文件状态标志(读,写,添,同步,非阻塞等信息)和当前文件偏移位,还有指向v(i)-node的指针。所以每个进程对于这个文件的操作偏移位不是共享的,这将会涉及到数据同步的问题,详情参考《Unix高级环境编程》3.10 文件共享 章节.

    20.有些例外的情况,不同的进程或同进程不同的fd会引用同一个文件表,例如用来复制fd的dup函数和fork子进程时会发生这样的情况.

    21.除root用户外,其余用户只能编辑属于自己名下的文件权限位,详情参考《Unix高级环境编程》4.9 章节.

    22.只有root用户可以更新文件的所有者UID,而关于组GID,只有文件所有者可以修改组GID,详情参考《Unix高级环境编程》4.11 章节.

    23.目录拥有者可以删除该目录下不属于自己或者不具备权限的文件.

    24.一些文件系统不允许用户对目录创建硬链接(就算允许,也仅限于超级管理员),这是因为需要避免循环访问的原因,详情参考《Unix高级环境编程》4.15 章节.

    25.一个文件只有一个iNode.

    26.目录文件的block保存的是该目录下的目录项,目录项包含一个文件名和一个指向该文件iNode的指针.

    27.重命名(或者改变文件路径),实际上是删除原有的目录项,新建一个指向该iNode的目录项.

    28.硬链接会在block中创建目录项,目录项指向和这个文件的其他硬链接(如果有)同一个iNode上,关于这个iNode,每增加一个硬链接,就会在它的引用次数(stat.st_nlink)上加1,当删除该文件时,其实只是删除引用这个iNode的目录项,并且会在这个iNode的引用次数上减1,直到引用次数为0时,系统调用才会真正删除这个iNode,并回收它指向的block.

    29.软连接则是一个单独的文件,拥有单独的iNode,这个文件的iNode表项中S_IFLNK表明这个文件是一个符号链接,iNode指向block,而block中包含了需要指向的文件的完整文件名(参考《Unix高级环境编程》4.14 章节),删除它并不影响它指向的文件.

    30.硬链接要求文件在同一个文件系统,而软连接可以跨文件系统。只有超级用户才有权限为目录增加硬链接.

    31.mkdir创建新文件目录时,会自动创建.和..这两个目录项,它们分别指向自己和自己的上一级,详情参考《Unix高级环境编程》4.21 章节.

    注1|进程表项

    标志 说明
    close_on_exec 通常0(系统默认,exec时不关闭)或1(在exec时关闭),但是标准起见,POSIX定义了FD_CLOEXEC这个常量,代表在exec时关闭
    文件指针 指向文件表项的指针

    *如表格所示,Unix系统目前只定义了一种文件描述符标志

    注2|文件表项

    标志 说明
    文件状态标志 打开文件的方式标志位
    当前文件偏移量  
    v(i)-node指针 指向v(i)-node的指针

     

  • 相关阅读:
    HTTP断点续传 规格严格
    Java Shutdown 规格严格
    linux 命令源码 规格严格
    JTable调整列宽 规格严格
    linux 多CPU 规格严格
    Hello can not find git path 规格严格
    Kill 规格严格
    拜拜牛人 规格严格
    Swing 规格严格
    Debugging hangs in JVM (on AIX but methodology applicable to other platforms) 规格严格
  • 原文地址:https://www.cnblogs.com/yiyide266/p/9651784.html
Copyright © 2011-2022 走看看