Почему mode_t использует 4 байта? - PullRequest
6 голосов
/ 07 марта 2012

Я только что прочитал о 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 Ответ

10 голосов
/ 07 марта 2012

Давайте посмотрим, что будет делать «тупой» компилятор, если ему дан следующий код:

#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
            ...

Посмотрите, как специальная инструкция movzwl необходима для загрузки 16-битного значения? Это связано с тем, что он должен быть расширен до двух дополнительных байтов для размещения в регистре. Очевидно, что эта инструкция более сложна, чем простая mov. Это может незначительно повлиять на производительность и увеличить размер исполняемого файла на несколько байтов, что само по себе не так уж и плохо.

Однако, если учесть, что использование 16-битного значения не дает никаких преимуществ, поскольку в любом случае из-за выравнивания оно обычно занимает 32 бита, в любом случае понятно, почему разработчики решили использовать собственный размер слова: процессор здесь.

...