Каковы двоичные представления флагов, используемых в системном вызове Linux open()?

Я изучаю NASM и в настоящее время не уверен, какие значения следует использовать в качестве аргумента флагов для open(), как показано на справочной странице . В основном я спрашиваю об этом для разъяснений, чтобы ничего не испортить, и прошу прощения, если это не подходит для сайта.

Я прочитал справочную страницу, но не смог найти, перечислены ли скрытые значения, но поскольку он и этот SO ответ сказали, что они предназначены для побитового ИЛИ, я предположил, что они действуют как битовые флаги (вероятно, следовало бы понять это из названия). Посмотрев здесь, я нашел их в «/usr/include/asm-generic/fcntl.h» на своем компьютере (Ubuntu). Этот раздел с флагами выглядит так, за исключением некоторых строк:

#define O_ACCMODE   00000003
#define O_RDONLY    00000000
#define O_WRONLY    00000001
#define O_RDWR      00000002
#define O_CREAT     00000100    /* not fcntl */
#define O_EXCL      00000200    /* not fcntl */
#define O_NOCTTY    00000400    /* not fcntl */
#define O_TRUNC     00001000    /* not fcntl */
#define O_APPEND    00002000
#define O_NONBLOCK  00004000
#define O_DSYNC     00010000    /* used to be O_SYNC, see below */
#define O_DIRECT    00040000    /* direct disk access hint */
#define O_LARGEFILE 00100000
#define O_DIRECTORY 00200000    /* must be a directory */
#define O_NOFOLLOW  00400000    /* don't follow links */
#define O_NOATIME   01000000
#define O_CLOEXEC   02000000    /* set close_on_exec */

#define __O_SYNC    04000000
#define O_SYNC      (__O_SYNC|O_DSYNC)
#define O_PATH      010000000
#define __O_TMPFILE 020000000
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)

Я увидел, что ведущий ноль означает, что значения находятся в системе счисления с основанием 8, поэтому я записал их вот так в двоичном формате (я не уверен, что это стандартный способ записи в двоичном формате), в порядке значения:

O_RDONLY    = 0b                            0   /* was 0o0 */
O_WRONLY    = 0b                            1   /* was 0o1 */
O_RDWR      = 0b                           10   /* was 0o2 */
O_ACCMODE   = 0b                           11   /* was 0o3 */
O_CREAT     = 0b                     100 0000   /* was 0o100 */
O_EXCL      = 0b                    1000 0000   /* was 0o200 */
O_NOCTTY    = 0b                  1 0000 0000   /* was 0o400 */
O_TRUNC     = 0b                 10 0000 0000   /* was 0o1000 */
O_APPEND    = 0b                100 0000 0000   /* was 0o2000 */
O_NONBLOCK  = 0b               1000 0000 0000   /* was 0o4000 */
O_DSYNC     = 0b             1 0000 0000 0000   /* was 0o10000 */
O_DIRECT    = 0b           100 0000 0000 0000   /* was 0o40000 */
O_LARGEFILE = 0b          1000 0000 0000 0000   /* was 0o100000 */
O_DIRECTORY = 0b        1 0000 0000 0000 0000   /* was 0o200000 */
O_NOFOLLOW  = 0b       10 0000 0000 0000 0000   /* was 0o400000 */
O_NOATIME   = 0b      100 0000 0000 0000 0000   /* was 0o1000000 */
O_CLOEXEC   = 0b     1000 0000 0000 0000 0000   /* was 0o2000000 */
O_SYNC      = 0b  10 0000 0000 0000 0000 0000   /* was 0o10000000 */
O_TMPFILE   = 0b 100 0000 0000 0000 0000 0000   /* was 0o20000000 */

Я предполагаю, что некоторые из них имеют обозначающие значения в одних и тех же битах, поэтому они не используются одновременно. Сделал ли я что-то не так в этом процессе, или это правильные значения для использования их в качестве флагов для системного вызова open()?

Почему бы просто не поместить их в восьмеричный формат, чтобы не переводить в двоичный?

Barmar 12.07.2024 00:22

@Barmar Я думал, мне будет легче понять, когда одновременно используются два флага, а также отладку. Я не знал, как реализованы флаги, поэтому спросил, не ошибаюсь ли я.

dundermouse 12.07.2024 00:32

Логика в порядке. Мы надеемся, что вы смогли ввести значения в любой калькулятор. Мы не будем проверять их по отдельности. Также обратите внимание: nasm поддерживает восьмеричные константы (хотя и не обозначаются префиксом 0) и может выполнять побитовое ИЛИ, поэтому на самом деле нет необходимости ничего преобразовывать.

Jester 12.07.2024 00:34
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это правильные значения в вашей системе. Нет никакой гарантии, что они будут такими же в другой системе. Вот почему вы используете заголовки, которые содержат правильные номера для вашей системы.

Кстати, это предположение неверно:

Я предполагаю, что некоторые из них имеют обозначающие значения в одних и тех же битах, поэтому они не используются одновременно.

Они гарантируют, что они будут переданы в одно и то же время, он не может ничего сделать, чтобы гарантировать, что они не будут переданы в одно и то же время (например, никто на самом деле не передает __O_SYNC, они проходят O_SYNC, и для библиотеки нет возможности в первую очередь отличить проходящий O_SYNC | O_DSYNC от O_SYNC).

Для конкретных перекрывающихся флагов:

  • O_ACCMODE — это не передаваемый вами флаг, это маска, используемая для извлечения части битов, указывающих режим доступа. Для вас это не имеет значения, но разработчикам open полезно иметь возможность маскировать эти конкретные биты (или инвертировать маску и маскировать другие биты), чтобы разделить режим доступа (чтение, запись или чтение). write) от всех остальных битов, указывающих на изменения поведения, не связанные с доступом.

  • O_SYNC состоит из двух битов (собственный уникальный бит и O_DSYNC), поскольку поведение O_SYNC является надмножеством O_DSYNC (O_DSYNC обеспечивает синхронизацию всех данных после каждой записи, O_SYNC также обеспечивает синхронизацию метаданных), поэтому все O_DSYNC должно bedoing также должно выполняться с помощью O_SYNC, и в некоторых частях кода удобно устанавливать оба бита для логики.

  • O_TMPFILE включение O_DIRECTORY является странным, потому что на самом деле вы не открываете каталог логически, но любой вызов, использующий O_TMPFILE, должен передать ему путь к существующему каталогу, а не файлу, поэтому, по-видимому, разработчики сочли удобным для проверки работоспособности сделать проверку «они передали нам каталог, а не имя файла» таким же образом для открытия каталога, как и для открытия временного файла в каталоге, а тайное включение флага O_DIRECTORY упрощает эти проверки.

Наверное, я придавал больше значения конкретному, чем нужно. Что касается значений, хранящихся в одном и том же бите, я в основном имел в виду, что O_RDONLY и O_WRONLY нельзя использовать одновременно, поскольку первый бит флага не может быть одновременно равным 0 и 1. Я даже не стал обратите внимание на аспекты тех, о которых вы говорили, так что спасибо за это.

dundermouse 12.07.2024 01:30

@dundermouse: O_RDONLY на самом деле даже не является флагом, поскольку никакие биты не установлены, но да, это тот случай, когда поведение по своей сути несовместимо (тем не менее, ничто не мешает вам передать оба, но когда вы передаете O_RDONLY | O_WRONLY, это , по сути, идентично простому прохождению O_WRONLY). Это довольно странный дизайн, как и следовало ожидать, там будут флаг O_READ и флаг O_WRITE (оба используют реальный бит, поэтому O_RDWR — это просто комбинация двух битов), но это не так. O_RDONLY по сути предназначен для людей, он ничего не «устанавливает».

ShadowRanger 12.07.2024 01:40

Первоначально это было перечисление: 0 — только для чтения, 1 — только для записи, 2 — для обоих. В наши дни ОС добавляет единицу к аргументу, передаваемому системному вызову open, и интерпретирует результат как растровое изображение.

fuz 12.07.2024 10:53

@fuz: Мило, это имеет смысл.

ShadowRanger 12.07.2024 12:28

Другие вопросы по теме