LINUX.ORG.RU

Как работает открывание stdin по символьному имени?

 ,


0

1
$ ls -1 /dev/std*
/dev/stderr
/dev/stdin
/dev/stdout

Если я открываю файл, передавая ему эти имена в качестве строки в параметр «имя файла».

В каком месте софта эти строки будут заменяться на стандартны хендлы? Эти константы зашиты в ядро Linux? Или этим занимается udev? Или как это работает? udev при чём или не при чём?

Ответ на: комментарий от Einstok_Fair

Как насчёт подумать? stdin - нулевой файловый дескриптор у каждого процесса, stdout - первый, stderr - 2. Ещё можно сделать stdlog 3 и любые другие.

Nuna
()
Ответ на: комментарий от Nuna

Я рад за эти числовые константы. Однако подумай сам, ответил ли ты на вопрос, какой кусок софта отвечает за сопоставление строк и этих констант?

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

Софт и отвечает. Полагаю, libc в данном случае. Со стороны софта это просто дескриптор в процессе. Процессами заведует ядро.

Nuna
()
Ответ на: комментарий от Nuna

Полагаю, libc в данном случае.

данунеможет быть. Ведь имя /dev/stdin - системное, а программа может быть написана и без использования libc (например на другом языке).

Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 1)
Ответ на: комментарий от Einstok_Fair

А что тебе не понятно в выводе?
Там вполне понятно написано, имеет ли отношение /dev/std* к udev, или нет. И как они заменяются на стандартные хэндлы.

uCore
()
Ответ на: комментарий от Einstok_Fair

Никто не заменяет. Это симлинки файловой системы и posix. Udev никаким боком к ним не относится, но он может плодить произвольные ссылки для произвольных потоков согласно своим правилам.

Nuna
()
Ответ на: комментарий от Nuna

Udev никаким боком к ним не относится

Я думал, что при старте /dev совсем пустой и всё что там создаётся - создаётся udev-ом. Можно конечно и руками заранее создать, но разве не Udev создает эти std* ?

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Nuna

Никто не заменяет.

версия с libc и то более правдоподобна. Если бы не заменял никто, то программа бы не работала, потому что строки это не целые.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

https://en.wikipedia.org/wiki/Procfs

ты просто не понимаешь что такое дескрипторы и почему мы их любим

при старте /dev совсем пустой

udev задаёт ссылки для устройств динамически, никто не запрещает тебе делать это же ручками.

Nuna
()
Ответ на: комментарий от Nuna

ты просто не понимаешь что такое дескрипторы и почему мы их любим

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

$ readlink /proc/self/fd/0
/dev/pts/3

Теперь объясняю, что не понимаешь ты. Ты не говоришь какая связь между символьным именем в procfs и дескриптором.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

что мне нужно увидеть?

/proc/self/fd/0 — это тоже ссылка. В конце концов цепочка /dev/stdin -> /proc/self/fd/0 -> *какой-то файл* приводит к реальному файлу на ФС или устройству, который и будет открыт.

anonymous
()
Ответ на: комментарий от anonymous

приводит к реальному файлу

Приводит к имени файла. И какой-то код должен выполнить все эти разыменования и получение целого числа. Где он, этот код? Он состоит из одной части или из нескольких?

Einstok_Fair ★★☆
() автор топика

В каком месте софта эти строки будут заменяться на стандартны хендлы?

Ядро проследует по ссылкам и откроет тот же файл (устройстви), что открыт для нулевого дескриптора. «Заменяться» оно не будет, вернётся хэндл, указывающий на тот же файл, что хэндл 0 (1, 2).

anonymous
()
Ответ на: комментарий от anonymous

интернет не анонимен, модераторы и твой провайдер выдадут информацию о месте твоего проживания в рамках следственных мероприятий. Сидеть тебе за хулиганство 15 суток.

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

что оно «преодразовывает»? это и есть дескриптор, числовые значения и алиасы для них хранятся в libc

Nuna
()
Ответ на: комментарий от Nuna

числовые значения и алиасы для них хранятся в libc

Из этого логически не следует, что преобразованием занимается так же libc

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

Преобразованием чего? Это просто ссылка на структуры в ядре, и libc должна знать как получить к ним доступ _в этом конкретном ядре_ или предложить альтернативу.

Nuna
()
Ответ на: комментарий от Nuna

какой кусок софта отвечает за сопоставление строк и этих констант?

Полагаю, libc в данном случае.

числовые значения и алиасы для них хранятся в libc

Это просто ссылка на структуры в ядре, и libc должна знать как получить к ним доступ _в этом конкретном ядре_

Неправда. man 2 open, man 2 read, man 2 write — это всё системные вызовы в ядро. libc никакого доступа к структурам ядра не имеет.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 3)

Что-то начинает казаться. что, как часто бывает, вопросы заданы не те, на которые нужен ответ. Предлагаю попробовать начать с начала. Если нужно работать со стандартными потоками - /dev/std* не требуются вообще-то. Литерал stderr в например

 fprintf(stderr,...);
с именем файла /dev/stderr не имеет прямой связи. Это только некое соглашение, облегчающее понимание, что с чем связано. /dev/std* требуются далеко не всем программам, работающим со стандартными потоками. Это не значит, что их можно удалить в произвольном дистрибутиве, но попробовать сделать сборку, работающую без них, наверно можно.

Elyas ★★★★★
()
Последнее исправление: Elyas (всего исправлений: 1)
Ответ на: комментарий от Elyas

Литерал stderr в например с именем файла /dev/stderr не имеет прямой связи.

я не знал, что stderr - это литерал. Всегда думал, что это непосредственно дескриптор (целочисленная константа).

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Elyas

Нет, у меня есть тайная цель. Я использую язык, отличный от C. И в нём нет переменной или константы, аналогичной stderr в языке C. Мне нужно понять, как это должно работать, если вместо этого использовать открытие файла по имени. Например сейчас оно не работает, выдаёт ошибку «совместного доступа к файлу».

Просто развлекаетесь?

Хамите, парниша?

Einstok_Fair ★★☆
() автор топика
Последнее исправление: Einstok_Fair (всего исправлений: 2)
Ответ на: комментарий от Einstok_Fair

Ну вот, уже ближе к сути. Итак, предположим, что в вашем секретном языке нет явного способа добраться до стандартного потока ошибок. Попытка открытия /dev/stderr после разрешения ссылок приводит к попытке открытия файла/устройства, связанного со стандартным потоком ошибок текущего процесса и ошибке. Что наводит на подозрения, что рантайм поддержка вашего языка выставляет монопольный доступ к этому файлу, либо ещё какие причины, но явно намекает, что поток существует и занят. То есть вопросы больше не к ядру, udev и т.п. а к среде исполнения конкретной программы.

Elyas ★★★★★
()
Ответ на: комментарий от Elyas

Как вариант - открытие файла в вашем языке по умолчанию предполагает монопольный режим - возможно это управляется дополнительными параметрами или ещё как-то.

Elyas ★★★★★
()
Ответ на: комментарий от Harald

Да... Но речь была про то что либц никак не связана с потоками. Насколько я помню, внутри оно вызывает те же системные вызовы и просто предоставляет удобный интерфейс. Остальное всё ещё валидно вроде бы.

Nuna
()
Ответ на: комментарий от Elyas

Итак, мы выяснили, что
1) преобразованием строк символов в дескрипторы файлов занимается ядро и libc не нужен.
2) в ядре есть таблица открытых файлов и при повторном обращении с такой же строкой возвращается тот же дескриптор

пока всё правильно?

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

1) да.

2) Нет.

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

Elyas ★★★★★
()
Ответ на: комментарий от Elyas

«The freopen function closes the file currently associated with stream and reassigns stream to the file specified by path.»

Тут два разных слова. Первое слово «stream», а второе слово «file».

Einstok_Fair ★★☆
() автор топика
Ответ на: комментарий от Einstok_Fair

Ну да. stream в конкретной программе. file в ОС. stream можно связать с файлом. Несколько stream можно связать с одним файлом. Поскольку это может вызвать проблемы, существуют блокировки, режимы доступа. Вот на этом моменте и возникает ошибка. Вокруг этого и следует искать либо методы обхода, либо вообще другое решение.

Elyas ★★★★★
()
Ответ на: комментарий от Tayler

В моей стране интернет заблокирован, извините.

Nuna
()
Ответ на: комментарий от Nuna

3 — это сишные библиотечные функции. А я говорю тебе про системные вызовы, это категория 2.

intelfx ★★★★★
()
Ответ на: комментарий от Nuna

$ man 2 open
No manual entry for open in section 2

Без понятия, чини систему.

intelfx ★★★★★
()
Ответ на: комментарий от Nuna

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

Совершенно справедливо.

Но файловые дескрипторы выдаёт именно ядро и оно же ведёт их учёт. А глобальная переменная stdin — это действительно libc-шная абстракция, если ты об этом, но она не имеет никакого отношения к файловым дескрипторам.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.