为什么mode_t使用4个字节?

时间:2012-03-07 13:48:24

标签: c permissions filesystems

我刚刚读到有关mode_t的信息,它基本上存储了以下信息:

  • 文件类型的7个布尔值(S_IFREG,S_IFDIR,S_IFCHR,S_ISBLK,S_ISFIFO,S_ISLINK,S_ISSOCK)
  • 3 * 3 =访问权限的9个布尔值(所有者,组和其他人的读,写和执行)

所以需要16位= 2个字节。我猜你甚至可以少一点文件类型,因为它必须是常规文件,目录,字符或块设备,套接字,符号链接或管道。或者存在其他文件类型吗?

所以我刚刚用

检查了mode_t的大小
printf("Size: %d byte\n", sizeof(mode_t));

它使用4个字节。为什么使用4字节?有没有我没注意到的其他信息?

编辑: 我刚刚发现mode_t在ptypes.inc中定义:

type mode_t = cuint32;

cuint32是32位大小的无符号整数,在ctypes.inc中定义:

type cuint32 = LongWord;

也许这有助于答案。

1 个答案:

答案 0 :(得分:10)

让我们看一下“dumb”编译器在给出以下代码时会做什么:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char **argv) {
  uint16_t test1 = 0x1122;
  uint32_t test2 = 0x11223344;
  if (test1 & 0x0100)
    printf("yay1.\n");
  if (test2 & 0x00010000)
    printf("yay2.\n");
}

这似乎是类型mode_t的值的可能用例,检查是否设置了标志。现在我们用gcc -O0编译它并检查生成的程序集:

0000000000000000 <main>:
            ...
   f:   66 c7 45 fe 22 11       movw   $0x1122,-0x2(%rbp)
  15:   c7 45 f8 44 33 22 11    movl   $0x11223344,-0x8(%rbp)
  1c:   0f b7 45 fe             movzwl -0x2(%rbp),%eax  ; load test1 into %eax
  20:   25 00 01 00 00          and    $0x100,%eax
  25:   85 c0                   test   %eax,%eax
            ...
  33:   8b 45 f8                mov    -0x8(%rbp),%eax  ; load test2 into %eax
  36:   25 00 00 01 00          and    $0x10000,%eax
  3b:   85 c0                   test   %eax,%eax
            ...

了解加载16位值需要特殊的movzwl指令吗?这是因为它需要符号扩展到另外两个字节以适合寄存器。显然,这条指令比简单的mov更复杂。这可能对性能产生很小的影响,并且可能会将可执行文件大小增加几个字节,这本身就不会太糟糕。

但是,如果我们认为使用16位值没有任何优势,因为由于对齐,它通常会占用32位存储空间,因此很明显为什么设计人员选择使用原始字大小这里的CPU。