Я изучаю 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 Я думал, мне будет легче понять, когда одновременно используются два флага, а также отладку. Я не знал, как реализованы флаги, поэтому спросил, не ошибаюсь ли я.
Логика в порядке. Мы надеемся, что вы смогли ввести значения в любой калькулятор. Мы не будем проверять их по отдельности. Также обратите внимание: nasm поддерживает восьмеричные константы (хотя и не обозначаются префиксом 0
) и может выполнять побитовое ИЛИ, поэтому на самом деле нет необходимости ничего преобразовывать.
Это правильные значения в вашей системе. Нет никакой гарантии, что они будут такими же в другой системе. Вот почему вы используете заголовки, которые содержат правильные номера для вашей системы.
Кстати, это предположение неверно:
Я предполагаю, что некоторые из них имеют обозначающие значения в одних и тех же битах, поэтому они не используются одновременно.
Они гарантируют, что они будут переданы в одно и то же время, он не может ничего сделать, чтобы гарантировать, что они не будут переданы в одно и то же время (например, никто на самом деле не передает __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: O_RDONLY
на самом деле даже не является флагом, поскольку никакие биты не установлены, но да, это тот случай, когда поведение по своей сути несовместимо (тем не менее, ничто не мешает вам передать оба, но когда вы передаете O_RDONLY | O_WRONLY
, это , по сути, идентично простому прохождению O_WRONLY
). Это довольно странный дизайн, как и следовало ожидать, там будут флаг O_READ
и флаг O_WRITE
(оба используют реальный бит, поэтому O_RDWR
— это просто комбинация двух битов), но это не так. O_RDONLY
по сути предназначен для людей, он ничего не «устанавливает».
Первоначально это было перечисление: 0 — только для чтения, 1 — только для записи, 2 — для обоих. В наши дни ОС добавляет единицу к аргументу, передаваемому системному вызову open
, и интерпретирует результат как растровое изображение.
@fuz: Мило, это имеет смысл.
Почему бы просто не поместить их в восьмеричный формат, чтобы не переводить в двоичный?