Чтобы один раз вызвать write. Версия из FreeBSD интереснее, она минимизирует переключения контекста вызовом writev и оптимальнее всех использует память.
что ты этим пытался доказать? Убогость и ущербность UNIX'а? Да, было такое. Тогда и техника тоже была убогой и ущербной, и современные coreutils на ней надо было лет двадцать компилять.
В случае Plan 9 системных вызовов тоже немного: segattach, а затем write. Кстати, вот все системные вызовы плана, если кому интересно: http://aiju.de/misc/plan9-syscalls
Нет потоков. Либо используешь libthread, где потоки разруливаются самой библиотекой, либо делаешь rfork и получаешь несколько процессов с общей памятью. Процессы в Plan 9 довольно легковесны, кстати.
В случае Plan 9 системных вызовов тоже немного: segattach, а затем write.
Я бы подумал, что там brk. Создается копия всех аргументов и разделителей. Ну и да, два раза strlen по всем аргументам, как уже сказали.
Во FreeBSD распределяется память только под небольшую структуру, размер которой зависит от количества аргументов, ничего не копируется, и результат выводится по одному сисколу на каждые 1024 аргумента.
я может чего не понимаю в сисколах, но где же потоки?
Там есть специальная разновидность процессов, которые шарят с родителем и bss, и data, создаются rfork с флагом RFMEM. Там вообще при создании форка можно выбирать, что унаследует потомок, что проинитится по дефолту, а что будет разделяться с родителем.
Возможно, brk. В любом случае, Plan 9 echo выделяет память под весь вывод, формирует его и передаёт указатель write. Вывод одним блоком требует выделения памяти.
по одному сисколу на каждые 1024 аргумента
Кто-то использует echo с количеством аргументов, превышающим 9000, и разработчики FreeBSD заботятся, чтобы блоки не были слишком большими?
Plan 9 echo выделяет память под весь вывод, формирует его и передаёт указатель write.
FreeBSD память не выделяет, а отправляет на вывод готовые строки из *argv[].
Вывод одним блоком требует выделения памяти.
Не обязательно, если есть системный вызов, которому можно передать список блоков.
разработчики FreeBSD заботятся, чтобы блоки не были слишком большими?
Нет, просто один вызов writev() берет из struct iovec не более IOV_MAX блоков. Думается, для подавляющего большинства запусков echo будет вызван один сискол.
Я в курсе, что в Plan 9 нет. Решение продиктовано необходимостью, во FreeBSD код написан из тех же предпосылок. Сперва отказались от буферизованного io, получив экономию по памяти и в размере бинарника (в пять раз во фре) просто заменив всякие printf, puts и putchar на write. А чтобы вернуть производительность пошли разными путями: в плане формируют одну строку из кусочков, а во фре есть сискол, умеющий много кусочков за один вызов. В остальном один фиг, фря только про \c ещё знает.
А в случае FreeBSD даже echo не назовёшь простым.
Да ну?
PS. Кстати, если бы в Plan 9 можно было заменить strcpy() на stpcpy(), избавились бы второго вызова strlen().
Ты не ругайся, а лучше объясни ему, чем различаются BSD echo и SysV echo. :)
не только
Что «не только»? До появления стандарта ANSI C (C89) была только K&R, то есть книга Брайана Кернигана и Денниса Ритчи «The C Programming Language» — первое и долгое время единственное руководство по языку.
Ты не ругайся, а лучше объясни ему, чем различаются BSD echo и SysV echo.
дык в коде всё вроде написано ясно.
Что «не только»? До появления стандарта ANSI C (C89) была только K&R, то есть книга Брайана Кернигана и Денниса Ритчи «The C Programming Language» — первое и долгое время единственное руководство по языку.
современный стиль тоже был возможен даже во времена K&R. Я ещё успел в срачах поучаствовать, какой стиль лучше. Или не так?
Не так. Декларации функций как в C++ стандартизированы в ANSI C, до этого были только расширением в некоторых свежих C/C++ компиляторах. В K&R также не было прототипов функций, типы аргументов выяснялись по первому использованию, поэтому в декларации могли отсутствовать (int) или быть по ошибке не теми. Вот не компилируемый пример:
main (c, v)
int c;
char *v[];
{
int i;
i = fun(c, v);
return 0;
}
fun (a, b)
{
return 1;
}
Чтобы избежать этого и не компилировать мусор, придумали lint, например.
Двадцать лет назад во всех BSD был один код, затем во FreeBSD добавили \c из iBCS2. Затем, лет десять назад, заменили библиотечный буферизованный вывод на вызов сискола write, что уменьшило размер файла и потребляемой им памяти в пять раз. Вот как бы так.