【问题标题】:C/Unix: How to extract the bits from st_mode?C/Unix:如何从 st_mode 中提取位?
【发布时间】:2016-05-24 08:08:56
【问题描述】:

我是 Unix 编程和 C 的初学者,我有两个关于 struct stat 及其字段 st_mode 的问题:

  1. 如下访问st_mode字段时,返回什么类型的数字(八进制、十进制等)?

    struct stat file;
    stat( someFilePath, &file);
    printf("%d", file.st_mode );
    

我以为数字是八进制的,但是当我运行这段代码时,我得到了值33188。基础是什么?

  1. 我发现st_mode 编码了一个代表文件类型和文件权限的16 位二进制数。如何从上述输出中获取 16 位数字(尤其是当它似乎不是八进制时)。 16 位数字的哪些部分编码了哪些信息?

感谢您的帮助。

【问题讨论】:

    标签: c linux file unix directory


    【解决方案1】:

    你把它打印为十进制,所以你得到了十进制。如果你把它打印成八进制,你就会得到八进制;十六进制同上。

    st_mode 字段在打印为八进制时最容易理解。

    printf("mode = %07o\n", file.st_mode);
    

    最后三位是熟悉的权限(例如 644)chmod 等。从右数第 4 位通常为 0,但对于 set-UID、set-GID 或 Sticky-bit 将是非零文件或目录。其余数字标识文件的类型。

    您可以使用来自<sys/stat.h> 的宏来剖析信息。

    【讨论】:

      【解决方案2】:
      1. 数字是一个值的集合。在printf() 中,您可以使用"%d" 以十进制形式打印(如您所做的那样),或者改用"%o"(或"%lo")以八进制形式打印。

      2. 检查man 2 stat 了解每个信息的表示方式。然后,您可以使用位掩码来提取您需要的信息。手册页中有一个示例。

      【讨论】:

        【解决方案3】:

        我认为你在这里混合了概念。

        在内存中,整数值总是二进制的,我们称之为原生格式st_modemode_t 类型,并且该类型是未指定的整数类型,可能是 int

        base 的概念,即十进制、八进制或十六进制,仅当您将内存中的本机格式的数字转换为文本表示(或从文本转换为本机)时才有用。

        例如:

        int x = 42;
        

        将数字 42 分配给整数变量。由于源代码是文本,所以42作为文本输入,我们知道它是一个十进制值(无前缀)。但请注意,我们没有为变量指定基数:它没有基数。 这个其他代码:

        int x = 0x2A;
        

        完全等价。它使用十六进制常量0x2A 而不是十进制常量42,但这是相同的,x 在两种情况下都得到相同的值。同样:

        int x = 052;
        

        也是等价的,但使用八进制常数。

        现在到您的代码。当你这样做时:

        printf("%d", file.st_mode);
        33188
        

        您告诉程序将该变量的值输出为十进制数。请记住,printf 将数字从本机格式转换为文本,因此该文本的基础很重要。如果您希望将值视为八进制,只需编写:

        printf("%o", file.st_mode);
        100644
        

        或十六进制:

        printf("%x", file.st_mode);
        81A4
        

        八进制的好处在于它代表每个八进制数字正好 3 位(十六进制每个数字 4 位),因此通过一些练习,您可以在不计算的情况下看到这些位。

        例如,您的st_mode 是十进制的33188 或八进制的0100644。十进制什么也没告诉我,但八进制确实意味着什么,因为我记得最后 9 位(3 个八进制数字)是权限:3 位用于所有者,3 位用于组,3 位用于其他。所以:

        * Owner: 6 that is rw-
        * Group: 4 that is r--
        * Other: 4 that is r--
        

        顺便说一句,最后一个是这个常数:

        #define S_IFREG 0100000
        

        这只是意味着它是一个常规文件。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-28
          • 2019-06-10
          • 1970-01-01
          • 1970-01-01
          • 2012-03-29
          • 2020-12-16
          • 1970-01-01
          相关资源
          最近更新 更多