• 文件属性之文件权限


    文件属性

    文件属性:我们通过ls查到就是文件属性,只不过ls只显示了部分文件属性

    学习操作文件属性的OS API,可以深入的理解文件

    文件属性的OS API
    • stat、fstat、lstat
    • umask
    • chown,fchown,lchown
    • link,unlink,remove,rename
    • symlink和readlink
    • chdir、和getcwd
    文件七种类型

    z-:普通文件d:目录文件c:字符设备文件s:套接字文件

    p:管道文件l:链接文件b:块设备文件

    1. 普通文件

    普通文件根据存放的内容的不同,分为:

    • 文本文件:存放的都是文字编码

    文本编辑器打开后,会将这些文字编码翻译为文字图形

    • 纯二进制文件(机器码):里面放的是cpu执行的纯二进制机器码

    用文本编辑器打开后,显示的内容无法是错乱的,无法辨识。

    其实不管存放的是文字编码,还是机器码,在计算机中存储时,其实都是以二进制形式存放的

    2. 目录文件

    目录是一种特殊的文件,专门用于管理其它文件。

    3. 字符设备文件

    字符设备文件就是字符设备驱动程序在上层的表现形式

    ​ 当应用程序想要实现对某个字符设备进行读写时,需要调用底层的字符设备驱动程序,上层就需要对接底层的字符驱动程序,字符设备驱动在上层会以“字符设备文件”的形式表现出来,我们通过open、read、write去读写字符设备文件,就实现了和底层字符设备驱动程序的交互。

    4. 块设备文件

    块设备文件,是块设备驱动程序在上层的表现形式

    字符设备与块设备有什么区别?
    字符设备: 以字节为单位来操作数据。比如:键盘、鼠标、显示器都等是字符设备。
    		  字符设备的驱动程序,就称为“字符设备驱动程序”
    块设备:   块设备存储的数据量往往非常大,为了提高读写效率,都是以块(1024字节)为单位来操作数据。
    	      比如电脑硬盘、移动硬盘、u盘等,凡是涉及大量数据存储的,都是以块为单位来操作数据的,都是块设备。
              块设备的驱动程序,就称为“块设备驱动程序”。
    底层驱动程序,就分为字符设备驱动和块设备驱动
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    5.管道文件(FIFO:p)

    管道文件,用于实现不同进程(程序)之间的通信,管道是OS提供的一种纯代码层面的通信机制。

    ​ 数据 数据
    ​ A进程 ————> 管道文件 ————>B进程

    6.套接字文件(socket)

    专门用于网络通信的文件

    7.符号连接(symbolic link)

    其实就是一种快捷图标,背后指向了另外一个文件

    这7类文件,其中普通文件数量最多,其次是目录文件,然后才是其它类的文件

    用file命令查看可执行文件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sygADNmj-1667035584893)(/home/guojiawei/.config/Typora/typora-user-images/image-20221029171904667.png)]

    • ELF:Linux下可执行文件的格式,Windows下的可执行文件是PE格式
    • 64-bit:文件里面的机器指令是64位的
    • LSB:小端序,C语言里面有详细介绍大小端序
    • executable:明确告诉你,该文件是一个可执行文件
    • x86-64:运行的是intel的i386的、64位的cpu
    • dynamically linked, /lib64/ld-linux-x86-64.so.2
      程序使用的库是动态链接库,库名叫/lib64/ld-linux-x86-64.so.2
    • for GNU/Linux 3.2.0:运行的系统是Linux系统(ubuntu),数字是版本号
    • not strippe:程序没有被瘦身,里面包含有各种用于调试用的信息。
    • 当这个程序最终发布时,会使用strip命令为程序瘦身,去除里面的无用信息,让程序变的更小。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lgky1Lrp-1667035584896)(/home/guojiawei/.config/Typora/typora-user-images/image-20221029172507271.png)]


    获取文件属性的函数:stat、lstat、fstat

    • 这三个是兄弟函数,实现的功能相同,只是略微有区别

    我们只要先把stat函数搞清楚了,lstat、fstat非常容易理解。

    • ls命令其实就是调用了这三个函数中的lstat来实现的,我们可以调用lstat函数来自己实现一个ls命令

    • 通过这三个函数的学习,深刻的理解文件各种属性,进而理解了“文件”是个什么东西

    1.stat
    函数原型
    #include 
    #include 
    #include 
    int stat(const char *pathname, struct stat *statbuf);
    
    • 1
    • 2
    • 3
    • 4
    函数功能

    功能就是获取文件的属性信息

    每个文件的属性信息,都是存在块设备上、该文件自己的inode节点空间中的。

    ​ 调用stat函数时,文件系统通过stat给的path,到块设备上索引到该文件的inode节点空间,然后将里面的文件属性信息,读到应用程序的缓存中,如此就得到了文件的属性信息。

    			            文件属性数据中转的过程:
    应用缓存 <———— stat函数提供的内核缓存 <———— 驱动程序的缓存 <————— 块设备上的inode结点
                  应用缓存:调用stat函数的应用在内存中开辟的应用缓存
    
    • 1
    • 2
    • 3
    返回值

    调用成功,返回0,失败返回-1,errno被设置。

    参数说明
           int stat(const char *path, struct stat *buf);
    (1)const char *path:文件路径名
    (2)struct stat *buf:应用缓存,用于存放读到的文件属性信息
    
    • 1
    • 2
    • 3

    #include
    #include
    #include 
    #include 
    #include 
    void print_error(char* str){
        perror(str);
        exit(-1);
    }
    int main(){
        int res=0;//存放返回结果
        struct stat sta={0};//存放应用缓存
         //int stat(const char *pathname, struct stat *statbuf);
        res=stat("mm.txt",&sta);
        if(res==-1) print_error("stat fail!");
        //把读入的内容打印
        printf("%d %lu %d %d %ld  %s\n",sta.st_mode,sta.st_nlink,sta.st_uid,\
                  sta.st_gid,sta.st_size,"mm.txt");
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YD0Qv6H-1667038127231)(/home/guojiawei/.config/Typora/typora-user-images/image-20221029180831808.png)]

    Linux都是以数字形式来管理属性信息的

    主函数传参数

    #include 
    #include 
    #include 
    #include 
    #include 
    void print_error(char* str){
        perror(str);
        exit(-1);
    }
    int main(int argc,char** argv){//main带参数
      int res=0;
      struct stat aaa={0};
      //argc---参数数量
      if(argc!=2) {printf("可执行程序+文件名"); exit(-1);}
      /*获取文件属性*/
      res=stat(argv[1],&aaa);//注意取地址,传的是指针
      if(res==-1)  print_error("stat fails!");
      /*打印文件属性*/
      printf("%d %ld %u %u %ld %ld %s",\
            aaa.st_mode,aaa.st_nlink,aaa.st_uid,aaa.st_gid,\
            aaa.st_size,aaa.st_atime,argv[1]);
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述


    7类文件都有的属性

    ino_t st_ino; / inode结点号 /
    mode_t st_mode; /* 文件类型和文件权限*/
    ​ nlink_t st_nlink; /* 链接数 /
    ​ uid_t st_uid; /
    文件所属用户ID*/
    ​ gid_t st_gid; /* 文件所属组ID /
    ​ off_t st_size; /
    文件大小 /
    ​ time_t st_atime; /
    最后一次访问时间,read*/
    ​ time_t st_mtime; /* 最后一次修改时间,write /
    ​ time_t st_ctime; /
    最后一次属性修改的时间,如权限被修改,文件所有者(属主)被修改 */

    专门给块设备文件用的
    -----1:dev_t     st_dev;         /* 块设备号 */ 
    -----2:blksize_t st_blksize;    /* 系统每次按块Io操作时,块的大小(一般是512或1024)*/
    -----3:blkcnt_t  st_blocks;  	/* 块的索引号 */
    ****
    专门给字符设备用的 
    -----dev_t     st_rdev;         /* 字符设备号(ID) */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    ls信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SBx6RcR2-1667053806193)(/home/guojiawei/.config/Typora/typora-user-images/image-20221029211406687.png)]

    • st_uid—表示文件的所属用户,用户id(用户编号)是唯一的

    • st_gid----多个用户可以在一起组成一个组,其中的某个用户会担任组长,该用户的用户id,就是整个组的组id

      ​ 对于普通用户而言,自己一个人就是一组,组员和组长都是自己,所以一般情况下,ls显示文件的所属组时,就是所属用户亲自担任组长的那个组,而且组员就自己一人

    st_mode属性

    ​ 介绍st_mode的目的是,希望通过st_mode的学习,深入理解文件权限这个东西。

    关键是理解,而不是记忆

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nmSHICnG-1667053806194)(/home/guojiawei/.config/Typora/typora-user-images/image-20221029214329707.png)]

    st_mode起到:表示文件类型和指定文件权限的双重作用

    st_mode的第一个符号代表文件类型,其他的表示的是“文件权限

    每三个为一组(rwx rwx r-x)

    第一个读权限,第二个写权限,第三个可执行权限

    每组第一个:如果是-,表示不能读,如果是r,表示可以读
    每组第二个:如果是-,表示不能写,如果是w,表示可以写
    每组第三个:如果是-,表示不可以被cpu执行,如果是x,表示可以被执行

    三组权限

    创建文件的用户;用户组里的其他用户;普通用户

    第一组:代表的是文件所属用户,对该文件的操作权限

    第二组:代表的是文件所属组里面,其它的组员用户,对该文件的操作权限

    第三组:除了所属用户、所属组以外的,其它用户对该文件的操作权限

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RLVZD24o-1667053806195)(/home/guojiawei/.config/Typora/typora-user-images/image-20221029215901641.png)]

    这里只有root可读写,所以guojiawei没有权限去写文件

    三组权限的大小关系

    • 正常情况下,所属用户的操作权限 >= 组员用户的操作权限 >= 其它不相干用户的操作权限
    把数字打印成字母形式

    st_mode为33200,对应的二进制为:1000(文件类型) 000 (设置位)110 110 000(文件权限)

    文件类型宏名

    为了方便使用,在Linux系统提供的stat.h头文件中,给数字定义了宏名

    #define S_IFREG 0100000 代表普通文件
    #define S_IFDIR 0040000 代表目录文件
    #define S_IFBLK 0060000 代表块设备文件
    #define S_IFCHR 0020000 代表字符设备文件
    #define S_IFIFO 0010000 代表管道文件
    #define S_IFSOCK 0140000 代表套接字文件
    #define S_IFLNK 0120000 代表符号链接文件

    如何取出12~15位的值,然后用于判断文件的类型

    • 使用c语言中的 & 操作即可实现
    • 使用屏蔽字0170000(1111000000000000)&st_mode,将013清零(屏蔽),留下的1215
    • 系统给这个屏蔽字定义了一个宏名,即#define S_IFMT 0170000

    如何快速判断文件类型

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J6WStYVx-1667053806196)(/home/guojiawei/.config/Typora/typora-user-images/image-20221029222922342.png)]

    /*文件属性自定义*/
      char file_type ='0';
      //判断
      if(S_ISLNK(aaa.st_mode))      file_type='l';
      else if(S_ISREG(aaa.st_mode)) file_type='-';
      else if(S_ISDIR(aaa.st_mode)) file_type='d';
      else if(S_ISCHR(aaa.st_mode)) file_type='c';
      else if(S_ISBLK(aaa.st_mode)) file_type='b';
      else if(S_ISFIFO(aaa.st_mode)) file_type='p';
      else file_type='s';
      printf("\n%c\n",file_type);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    从数字提取文件权限

    文件权限
    										rwx rwx r-x									                                         __________/\_________
    			文件类型    设置位     |                    |
    			* * * *    * * *      * * *   * * *   * * *
    
    • 1
    • 2
    • 3
    • 4

    如图:4位文件权限,3位设置位,三组文件权限,每组文件权限三位

    提取用户权限

    #define S_IRUSR 00400:对应的是0000 000 100 000 000,提取用户读权限
    #define S_IWUSR 00200:对应的是0000 000 010 000 000,提取用户写权限
    #define S_IXUSR 00100:对应的是0000 000 001 000 000,提取用户可执行权限

    提取用户组权限

    #define S_IRGRP 00040 (0000 000 000 100 000)
    #define S_IWGRP 00020 (0000 000 000 010 000)
    #define S_IXGRP 00010 (0000 000 000 001 000)

    提取其他用户权限

    #define S_IROTH 00004 (0000 000 000 000 100)
    #define S_IWOTH 00002 (0000 000 000 000 010)
    #define S_IXOTH 00001 (0000 000 000 000 001)

    比如提取例子中的st_mode值(33200)中的用户权限

    33200(十进制) = 1000000110110000(二进制)

    1000 000 110 110 000&0000 000 100 000 000 S_IRUSR
    1000 000 110 110 000 &0000 000 010 000 000 S_IWUSR
    1000 000 110 110 000 &0000 000 001 000 000 S_IXUSR

    #include
    #include
    #include 
    #include 
    #include 
    int main(int argc,char** argv){
        if(argc!=2) {
            printf("请输入文件路径和文件名");
            exit(-1);
        }
        struct stat _buf={0};
        int res=stat(argv[1],&_buf);//注意取地址
        //int stat(const char *pathname, struct stat *statbuf);
        /*打印文件权限--使用移位*/
        int i;
        char show_qx[]="rwxrwxrwx";
        char buf_qx[10]={0};
        for(i=0;i<9;i++){
            if(_buf.st_mode & (1<<(8-i))) {
              buf_qx[i]=show_qx[i];//值为1,&位真
            }
            else{
              buf_qx[i]='-';
            }
        }
        printf("%s\n",buf_qx);
      return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uXGaXOaH-1667210234920)(/home/guojiawei/.config/Typora/typora-user-images/image-20221031175702003.png)]

  • 相关阅读:
    中国大陆IP段(含港澳)【2024-04-25】APNIC lasted 2024-04-25
    小波系数等值线图和小波方差图绘制教学
    Node.js 实战 第1章 欢迎进入Node.js 的世界 1.4 Node 自带的工具 1.4.1 npm
    SSM学习——MybatisPlus快速入门(16)
    CLEARTEXT communication to XX not permitted by network security policy 报错
    详解FreeRTOS:FreeRTOS任务删除过程源码分析(进阶篇—2)
    Java8的 lambda Stream的 map 和 flatmap 方法区别 map和flatMap方法的用法
    LeNet网络复现
    【原创】常用元器件(电阻)选型之阻值识别-cayden20220910
    报错01__GAN网络
  • 原文地址:https://blog.csdn.net/weixin_47173597/article/details/127589654