написать системный вызов, какое количество байтов ограничено?

Прототип системного вызова записи:

ssize_t write(int fd, const void *buf, size_t count);

Параметр count не имеет знака, а возвращаемое значение знаковое.

На странице помощи написано:

В случае успеха возвращается количество записанных байтов (ноль означает, что ничего не было записано). В случае ошибки возвращается -1, а errno устанавливается соответствующим образом.

Однако в нем не говорится, каков предел параметра count. Он по-прежнему не говорит о поведении, когда количество больше SSIZE_MAX.

Учитывая, что запись — это системный вызов, который можно использовать для универсальных устройств/файлов/чего угодно, если устройство поддерживает операции записи больше, чем SSIZE_MAX, возвращаемый тип не может обрабатывать реальное количество записанных байтов.

Для меня не имеет смысла передавать число байтов без знака и в результате возвращать число байтов со знаком. Почему бы просто не передать подписанный номер?

Похоже, что прототип функции записи подвержен ошибкам или, по крайней мере, оставляет возможную дыру в пути.

Кто-нибудь знает подробности об этом или где я могу найти эту информацию?


person Marcus    schedule 21.09.2012    source источник
comment
Я сам этого не знаю, но я считаю, что ограничение составляет целое число без знака. Это означает, что вы должны быть в состоянии записать 4294967296 байт за один раз. Возвращаемое значение в этом случае будет -1 (и вам нужно будет проверить errno, чтобы убедиться, что это действительно ошибка)   -  person ATaylor    schedule 21.09.2012
comment
POSIX говорит, если значение nbyte больше {SSIZE_MAX}, результат определяется реализацией, поэтому справочная страница Linux отсутствует - она ​​должна это описывать.   -  person Fred Foo    schedule 21.09.2012
comment
Обычно пишут() маленькими кусками. Мне трудно представить ситуацию, когда запись гигабайтов с помощью одного системного вызова была бы хорошей идеей.   -  person willglynn    schedule 21.09.2012
comment
Я не хочу писать большой кусок данных. Проблема в том, что я пишу уровень абстракции платформы, и мне нужно создать оболочку для этой функции. Я использую это для сокетов. Я хотел бы понять проблемы, связанные с этой ситуацией.   -  person Marcus    schedule 21.09.2012
comment
@Marcus: Для сокетов ваш предел, вероятно, намного ниже, чем SSIZE_MAX, и привязан к размерам буфера, настроенным для сокета с помощью ioctl и/или setsockopt.   -  person Ben Voigt    schedule 21.09.2012
comment
Хорошо подмечено. Но я думаю об общем случае с использованием функции записи. Как я сказал в комментарии к сообщению ниже: если устройство поддерживает операции записи больше, чем SSIZE_MAX, возвращаемый тип не может обрабатывать реальное количество записанных байтов. Похоже, что прототип функции записи подвержен ошибкам или, по крайней мере, оставляет возможную дыру в пути.   -  person Marcus    schedule 21.09.2012
comment
@Marcus: безопаснее всего проверить в коде-оболочке, не превышает ли count SSIZE_MAX; или сделать его ssize_t и проверить, является ли он неотрицательным, в зависимости от того, что вам больше по вкусу. В любом случае, такие большие блоки — плохая идея.   -  person Fred Foo    schedule 21.09.2012
comment
Конечно. Спасибо за Ваш ответ.   -  person Marcus    schedule 21.09.2012


Ответы (3)


Я не думаю, что существует жесткое ограничение, это зависит от того, на что указывает fd. Например, если это файл в файловой системе, то драйвер файловой системы задохнется, если вы превысите «предел максимального размера файла», возвращая ошибку EFBIG:

EFBIG Предпринята попытка записи файла, размер которого превышает максимальный размер файла, определенный реализацией, или предельный размер файла процесса.

person Martin Wickman    schedule 21.09.2012
comment
Верно, этот параметр просто передается реализации для конкретного устройства. - person Ben Voigt; 21.09.2012
comment
Если fd относится к сокету (обычно неблокирующему), можно получить ENOMEM . - person alk; 21.09.2012
comment
Я не совсем беспокоюсь о случае сокетов. Суть в следующем: если устройство поддерживает операции записи большего размера, чем SSIZE_MAX, возвращаемый тип не может обрабатывать реальное количество записанных байтов. Похоже, что прототип функции записи подвержен ошибкам или, по крайней мере, оставляет возможную дыру в пути. - person Marcus; 21.09.2012
comment
@Marcus - В какой системе вы можете реально выделить буфер больше SSIZE_MAX? Я считаю, что ограничивает доступная память, а не устройство. - person Bo Persson; 21.09.2012
comment
@Bo Persson - Дело не в возможности сделать это. Дело в том, что интерфейс функции странный. Он говорит, что вернет количество записанных байтов, но на самом деле он не может этого сделать. В том, что описано как зависящее от реализации, есть большое НО. Однако я не смог найти никакой информации об этом для реализации Linux. - person Marcus; 21.09.2012
comment
@Marcus - Но он может вернуть количество байтов, если вы не напишете больше, чем SSIZE_MAX, что в моей системе составляет около 2 ^ 63. Как выделить буфер большего размера? - person Bo Persson; 21.09.2012
comment
@BoPersson, дело не в этом. Я знаю, что не собираюсь использовать это. Я хочу сказать, что подпись кажется немного странной. Особенно потому, что в стандарте указано, что counte › SSIZE_MAX определяется реализацией. Я не видел никакой информации на справочных страницах Linux по этому поводу. Я не пытаюсь быть разборчивым в этом. Это просто вопрос понимания вещей. - person Marcus; 21.09.2012

Погуглил:

Если значение nbyte больше {SSIZE_MAX}, результат определяется реализацией.

Источник: http://pubs.opengroup.org/onlinepubs/009695399/functions/write.html

person Analog File    schedule 21.09.2012
comment
Я знаю, что это определено реализацией (как указано в большинстве сообщений выше). Однако я не смог найти ни одного места, где это поведение объясняется для конкретной реализации. Я считаю, что реализация означает устройство/файловую систему/любую реализацию. Вы знаете какое-то место, где наблюдается такая ситуация? - person Marcus; 21.09.2012
comment
Реализация означает того, кто написал эту функцию. Вероятно, ваш поставщик компилятора или поставщик ОС. Проверьте документы компилятора или ОС. Поскольку вы отметили linux, вероятно, это GCC с библиотекой GNU C. К сожалению, документы для него gnu.org/software /libc/manual/html_node/ не указывайте поведение, определенное реализацией (может потребоваться подать отчет об ошибке в документации). Если только вы (как и многие) не считаете, что код — это документация, в этом случае просто посмотрите на код (в этом весь смысл открытого исходного кода). - person Analog File; 21.09.2012
comment
Пожалуй, я размещу баг-репорт. Спасибо. - person Marcus; 21.09.2012

Я думаю, помните, что система выделяет количество байтов, которое вы отдаете функции. Но я не уверен. Возможно, вы должны попробовать справочные страницы size_t и ssize_t.

person Simon MILHAU    schedule 21.09.2012
comment
Я ошибся, в папке include есть, но я не знаю в какой именно =S Надеюсь вы найдете! - person Simon MILHAU; 21.09.2012
comment
Не волнуйтесь! Спасибо за вашу помощь. :D - person Marcus; 21.09.2012