Как искать API в Linux

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Re: Как искать API в Linux

Сообщение xchgeaxeax » 19.12.2023 11:46:57

sts писал(а):ну судя по объяснению работает GetEnvironmentVariable верно

Нет. Там же ясно написано, что HOSTNAME является внутренней переменной интерпретатора bash и не экспортируется автоматически в запускаемые процессы. Т.е. если вы вручную не зададите эту переменную среды перед запуском вашей программы, её не будет доступно через GetEnvironmentVariable.

Вот есть программа, которая показывает все три описанных способа
Screenshot_20231219_101910.png

При её запуске через ./TestProg в ответ получаем
Screenshot_20231219_101950.png

Но если вручную экспортировать переменную HOSTNAME
т.е. команда запуска будет выглядеть так export HOSTNAME && ./TestProg или так env HOSTNAME=$HOSTNAME ./TestProg
Screenshot_20231219_102026.png

Тогда соответствующую переменную среды включат в переменные окружения перед запуском вашей программы.
С тем же успехом можно передавать вашей программе имя в параметрах записав что-то типа этого ./TestProg -HOSTNAME $HOSTNAME
Но согласитесь, что все это костыли в отличии от способа получения имени через вызов gethostname.

Добавлено спустя 39 секунд:
Screenshot_20231219_103936.png
У вас нет необходимых прав для просмотра вложений в этом сообщении.
xchgeaxeax
постоялец
 
Сообщения: 125
Зарегистрирован: 11.05.2023 03:51:40

Re: Как искать API в Linux

Сообщение Alexander » 19.12.2023 12:08:02

Ну да: было найдено и добавлено два работоспособных решения: fpUName при uses baseunix; и GetHostName при uses unix;
и разобрана ситуация с GetEnvironmentVariable.
Аватара пользователя
Alexander
энтузиаст
 
Сообщения: 771
Зарегистрирован: 18.12.2005 19:10:00
Откуда: оттуда

Re: Как искать API в Linux

Сообщение xchgeaxeax » 19.12.2023 12:42:58

Ещё один минус способов работы с переменной bash это то, что значение переменной не обновляется вместе с реальным hostname до перезапуска оболочки.
После вызова sethostname через su -c "./SetHostName abracadabra" выполнение export HOSTNAME && ./TestProg сработает вот так
Screenshot_20231219_113518.png
У вас нет необходимых прав для просмотра вложений в этом сообщении.
xchgeaxeax
постоялец
 
Сообщения: 125
Зарегистрирован: 11.05.2023 03:51:40

Re: Как искать API в Linux

Сообщение stikriz11 » 20.12.2023 09:55:05



Обилие бесполезных ссылок не увеличивает авторитета спамера хернией.

Добавлено спустя 6 минут 12 секунд:
Pavia писал(а):Перевод доступен тут:
https://sourceforge.net/projects/man-pages-ru/
Исходники лежат на kernal.org а обсуждение идет через рассылку.

Большое спасибо за эту ссылку. Это очень полезно. Есть один вопрос. Там сишные заголовочные файлы в которых объявлены функции. Мне надо поставить сишный компилятор, чтобы узнать в какой so или где это все реадизовано? Я просто не понимаю. Вот, API Windows где-то в dll ках. API Linux в so?

Добавлено спустя 20 минут 25 секунд:
Чтобы было понятно что именно нужно, я приведу пример с получением имени компьютера:
LibHandle := LoadLibrary(PChar('ibc.so.6'));
ssGetHostName := GetProcAddress(LibHandle, PAnsiChar(AnsiString('gethostname')));
Вот это - тот уровень на котором можно считать, что задача поиска API решена.
А не парсить вывод с каких-то программ консоли, и уж конечно не читать некий файлик непонятно где неряшливо разбросанный по запутанным каталогам операционки.
stikriz11
постоялец
 
Сообщения: 126
Зарегистрирован: 04.09.2023 15:54:19

Re: Как искать API в Linux

Сообщение alexs » 20.12.2023 16:46:33

stikriz11 писал(а):А не парсить вывод с каких-то программ консоли, и уж конечно не читать некий файлик непонятно где неряшливо разбросанный по запутанным каталогам операционки.

Не надо пытаться переносить опыт работы в windows на другие системы.
Работа с файлами - это стандарт.
Фалы в системе разложены согласно стандарта.
Аватара пользователя
alexs
долгожитель
 
Сообщения: 4060
Зарегистрирован: 15.05.2005 23:17:07
Откуда: г.Ставрополь

Re: Как искать API в Linux

Сообщение xchgeaxeax » 20.12.2023 17:14:13

stikriz11 писал(а):и уж конечно не читать некий файлик непонятно где неряшливо разбросанный по запутанным каталогам операционки.

Я вам не файлик предлагал прочитать. Это данные ядра linux доступные через файловый интерфейс. Почитайте подробнее про каталог proc. Но он не стандартизирован и информацию предпочтительнее брать из системных вызовов.

Системные вызовы не надо ни откуда импортировать. Это напрямую точки переключения из пользовательского режима в режим ядра. Если смотреть с точки зрения процессора, то все системные вызовы это просто один из параметров функции обработки команды syscall (для платформы x86_64) или int 128 (для платформы x86_32 или x86). Таблицу всех вызовов можете найти в man pages выполнив следующую команду man syscall или по ссылке https://chromium.googlesource.com/chrom ... yscalls.md

Все остальные функции из динамических библиотек (.so) это все отдельные проекты, по которым существуют отдельные описания функций и прототипов.
Если хотите работать в .so библиотеками как с dll, тогда вот ссылка https://www.math.uni-leipzig.de/pool/tu ... ode13.html
xchgeaxeax
постоялец
 
Сообщения: 125
Зарегистрирован: 11.05.2023 03:51:40

Re: Как искать API в Linux

Сообщение stikriz11 » 20.12.2023 18:33:57

syscall вызывается откуда? Я знаю как so подключать к своему проекту и как получать точку входа. А syscall? Там so? Или там розовые пони? Я же просто вопрос задал - очень просто. Почему надо говорить умные фразы, которые ничего не значат вообще? Вы не знаете? Вы сами читали то, на что ссылку даете? Там заголовочный файл инклуд сишный. И в нем, по идее, есть получение точек входа в syscall. Я же спросил. Мне надо сишный компилятор установить, чтобы узнать как линкуются апишные функции? Вы сами то понимаете о чем говорите? Откуда такой снобизм?

Добавлено спустя 1 минуту 18 секунд:
alexs писал(а):Работа с файлами - это стандарт.

Это дурость от безисходности или от лени и нежелании разбираться?

Добавлено спустя 2 минуты 47 секунд:
Я понял, что на этом можно остановится. Дайте мне время, я приду и расскажу как надо делать. Всем успеха. Тем, кто помог - огромное спасибо. Тем кто потрепаться зашел, не волноваться по пустякам.

Добавлено спустя 2 минуты 5 секунд:
xchgeaxeax писал(а):Системные вызовы не надо ни откуда импортировать. Это напрямую точки переключения из пользовательского режима в режим ядра.

Да...
stikriz11
постоялец
 
Сообщения: 126
Зарегистрирован: 04.09.2023 15:54:19

Re: Как искать API в Linux

Сообщение xchgeaxeax » 20.12.2023 20:18:04

stikriz11 писал(а):А syscall?

...

Да...

syscall это инструкция процессора (для архитектуры x86_32 или просто x86 - 32-битной используется другая инструкция процессора - int 128). Их не надо ни откуда экспортировать. Они доступны всем программам.
Перед использованием этой инструкции, которая осуществляет вызов программы ядра, надо подготовить параметры вызова. Один из параметров (первый) идентифицирует тип вызова. Набор этих идентификаторов перечислен по ссылкам выше и представляет собой перечислительное множество начинающееся с 0 и до максимально документированного. Остальные параметры подготавливаются уже в зависимости от типа вызова.

В варианте на ассемблере (FASM) вот такая программа (текст после ; до конца строки это комментарий)
Код: Выделить всё
format ELF64 executable 3 : директива компилятору, которая создаст исполняемый файл Linux x86_64
segment executable        : директива компилятору для создания исполняемого сегмента в файле программы
entry $                   ; директива компилятору, которая показывает на точку входа в программу. исполнение программы начнётся с инструкции на следующей строке
    mov eax, 1            ; SYS_write - вызов записи в файл (По сути инструкция mov eax, 1 эквивалентна eax := 1 для варианта на Pascal)
    mov rdi, 1            ; stdout - стандартный файловый описатель консольного вывода (По аналогии с предыдущей инструкцией эта означает rdi := 1)
    mov rsi, msg          ; указатель на буфер для вывода на экран (eax, rdi, rsi, edx и dil это именованные ячейки памяти в центральном процессоре (регистры), а не переменные в оперативной памяти компьютера)
    mov edx, msg_len      ; длина буфера, байт (Т.е. перед выполнением инструкции syscall необходимо подготовить параметры вызова в определённых регистрах процессора)
    syscall               ; А вот эта команда как раз и будет выполнять вызов. Она передаст управление ядру Linux, которое выполнит вывод на экран строки в текущий терминал для этой программы

    mov eax, 60           ; SYS_exit - системный вызов завершения процесса
    mov dil, 0            ; код выхода (EXIT_SUCCESS)
    syscall               ; А вот теперь эта же команда выполнит вызов, который убьёт текущий процесс по его желанию (т.е. уже будет выполнен вызов SYS_exit, а не SYS_write как в первом случае)

; А это просто текстовая строка
msg db 'Hello, xchgeaxeax', 10
msg_len = $ - msg         ; И количество занимаемых ею байт
При этом я тут никаких библиотек не использую и программа работает

Но если посмотрите на эти вызовы они используют стандартные регистры для размещения параметров. Поэтому для ЯВУ существуют функции переходники, чтобы параметры системных вызовов правильно обрабатывались компилятором. Эти функции доступны с короткими именами (без приставки SYS_). Они все описаны в модуле unix.

А вот я эту программу загрузил в gdb и выполнил её
Screenshot_20231220_193316.png


Добавлено спустя 43 минуты 57 секунд:
Если выполнить программу, которую я тестировал на Pascal через strace (команда strace ./TestProg 2> TestProg.log), тогда мы увидим следующее (я обрезал вызовы, которые требуются fpc для инициализации и оставил только системные вызовы, которые сгенерировал код программы)
Код: Выделить всё
...

{Вот это вызовы, которые сгенерировал мой пример, читающий файл из /proc}
open("/proc/sys/kernel/hostname", O_RDONLY|O_LARGEFILE) = 3
read(3, "calculaten", 256)             = 10
close(3)                                = 0
write(1, "/proc/sys/kernel/hostname = 'cal"..., 41) = 41

{Вот этот вызов, который сгенерирован для вывода строки, получаемой из переменной среды}
write(1, "GetEnvironmentVariable('HOSTNAME"..., 41) = 41

{А вот функция-переходник gethostname использует системный вызов uname для получения структуры и копирует из этой структуры только одно из полей в строку результата}
uname({sysname="Linux", nodename="calculate", ...}) = 0
write(1, "GetHostName = 'calculate'rn", 27) = 27

{Вот эти вызовы сгенерированы для команды ReadLn вконце программы}
ioctl(0, TCGETS, {c_iflag=IXOFF|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ECHOE|ECHOK|ECHOCTL|ECHOKE, ...}) = 0
select(1, [0], NULL, NULL, {tv_sec=0, tv_usec=0}) = 0 (Timeout)
select(1, [0], NULL, NULL, NULL)        = 1 (in [0])
read(0, "r", 256)                      = 1
write(1, "33[1B", 4)                   = 4
ioctl(1, TCSETS, {c_iflag=ICRNL|IXON|IXOFF|IUTF8, c_oflag=NL0|CR0|TAB0|BS0|VT0|FF0|OPOST|ONLCR, c_cflag=B38400|CS8|CREAD, c_lflag=ISIG|ICANON|ECHO|ECHOE|ECHOK|IEXTEN|ECHOCTL|ECHOKE, ...}) = 0

...


Добавлено спустя 8 минут 36 секунд:
Для программы же на ассемблере будет показано только два системных вызова (execve не считаю, он остался от оболочки и я его не писал)
Код: Выделить всё
execve("./testFASM", ["./testFASM"], 0x7ffc36449550 /* 87 vars */) = 0
write(1, 0x40009c, 18)                  = 18
exit(0)                                 = ?
+++ exited with 0 +++
У вас нет необходимых прав для просмотра вложений в этом сообщении.
xchgeaxeax
постоялец
 
Сообщения: 125
Зарегистрирован: 11.05.2023 03:51:40

Re: Как искать API в Linux

Сообщение sts » 21.12.2023 13:14:37

xchgeaxeax писал(а):Нет. Там же ясно написано, что HOSTNAME является внутренней переменной интерпретатора bash и не экспортируется автоматически в запускаемые процессы. Т.е. если вы вручную не зададите эту переменную среды перед запуском вашей программы, её не будет доступно через GetEnvironmentVariable.

И? вы описали почему GetEnvironmentVariable работает верно, да, ей насрать на внутренние переменные левой программы, этих программ тыщи а она одна, а вот почему нет HOSTNAME в окружении это вопрос, такие вот "стандарты"
sts
постоялец
 
Сообщения: 431
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Re: Как искать API в Linux

Сообщение xchgeaxeax » 21.12.2023 14:27:34

sts писал(а):И?

И ничего. Механизм переменных окружения не предназначен ни для хранения ни для передачи сетевого имени.

Допустим у нас есть процесс, который параллельно запускает два дочерних процесса. Но перед запуском первого он устанавливает в своих переменных окружения HOSTNAME в значение 123, а перед запуском второго процесса ещё раз устанавливает HOSTNAME в 456. Тогда у первого дочернего процесса переменная окружения останется в значении 123, т.к. он получит копию этих переменных от родительского процесса во время его запуска, а у второго эта же переменная будет иметь значение 456. Даже если один из дочерних процессов изменит значение этих переменных скажем на 789, то об этом не узнает родительский процесс и у него значение HOSTNAME останется равным 456.

Начальные значения переменных окружения хранятся в файлах инициализации оболочки и для их перманентной установки надо прописать эти переменные в этих файлах. Но даже после этого изменения вступят в силу только после запуска новой копии оболочки или перезагрузки системы. В старом процессе оболочки переменные среды останутся без изменения.

Итого: механизм переменных окружения, к которому обращается GetEnvironmentVariable, не подходит для хранения значения системного параметра типа hostname. При изменении этого параметра обновлённое значение должно стать доступным всем процессам сразу же. Поэтому лучше не ограничиваться однократным получением hostname, а запрашивать его у системы периодически. Хотя бы раз в 100 мс через соответствующий системный вызов или функцию-переходник, чтобы реагировать на изменения, которые сделают в других процессах. И я не имею ввиду, что надо циклически его запрашивать и реагировать на изменения. Достаточно глобальную переменную, хранящую имя hostname, снабдить дополнительным значением time и перед использованием этой переменной проверять интервал времени прошедший с записанной точки. Если прошло больше 100 мс, то выполнять повторный системный вызов, а не использовать старое значение. Или просто каждый раз запрашивать его и не страдать фигней. А вот bash запрашивает значение hostname однократно при запуске и не реагирует на изменения этого параметра. Поэтому не стоит полагаться на значение локальной переменной HOSTNAME предоставляемой bash.

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

Добавлено спустя 20 минут 57 секунд:
P.S. Обратите внимание на этот скриншот, который я показывал в предыдущем ответе
Screenshot_20231220_193243.png

А именно посмотрите на значение распечатанные в правом нижнем углу. Это значения с вершины стека программы после её запуска. Первое из них это 1 - количество параметров в командной строке, а сразу после этой 1 (int argc) идёт два значения (char *argv[]). Первое это указатель на строку ./testFASM т.к. gdb запускал программу именно таким образом, а второе это 0 - конец массива. И вот сразу после этого массива в стеке расположен ещё один массив (char *environ[]), который содержит указатели на строки с переменными окружения и заканчивается нулевым указателем. Сами строки, судя по значению указателей, тоже находятся в стеке программы. Для архитектуры x86_64 минимальный размер страницы памяти составляет 4096 байт (или 0x1000). Т.е. программа получили полную копию этих данных и они не обновляются динамически т.к. стек ветви программы это сугубо интимный компонент программы, а все значения, включая и сами строки с именами и значениями переменных, уместились на одной странице памяти. Ядро для составления виртуального адресного пространства пользовательских программ использует страничный механизм и разделяемой памятью может быть только кратная страницам область памяти. А тут все на одной странице, включая и вершину стека. Но стек программы явно не может быть в общедоступной области памяти.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
xchgeaxeax
постоялец
 
Сообщения: 125
Зарегистрирован: 11.05.2023 03:51:40

Re: Как искать API в Linux

Сообщение WAYFARER » 21.12.2023 17:40:31

stikriz11, почитал я что вы пишите в ответ людям, которые вам действительно дельные советы дают и могу только посоветовать отказаться от идеи писать под линукс. Из этого ничего хорошего не выйдет. Вам дали ссылки на документацию, только вот пользоваться ей не получится, просто потому что не понимаете как оно работает и не знаете что искать.

Как можно не знать что такое системные вызовы (syscall), это же база? И это даже не про линукс...

xchgeaxeax, времени не жалко? У вас технический беграунд слишком разного уровня что бы он понял написанное.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Как искать API в Linux

Сообщение Снег Север » 21.12.2023 19:07:33

WAYFARER писал(а):Как можно не знать что такое системные вызовы (syscall), это же база?

Прекрасно можно - мне за 30+ лет работы в индустрии программирования это никогда не требовалось. И сейчас не требуется.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 3038
Зарегистрирован: 27.11.2007 16:14:47

Re: Как искать API в Linux

Сообщение WAYFARER » 21.12.2023 21:49:26

Снег Север писал(а):Прекрасно можно - мне за 30+ лет работы в индустрии программирования это никогда не требовалось.

Может быть, если твоя работа никак не связана с системным программированием, и то не уверен.
Аватара пользователя
WAYFARER
энтузиаст
 
Сообщения: 537
Зарегистрирован: 09.10.2009 00:00:04
Откуда: г. Курган

Re: Как искать API в Linux

Сообщение Снег Север » 21.12.2023 22:31:35

WAYFARER писал(а):никак не связана с системным программированием

Никак не связана. А тот минимум, который раз в 10 лет нужен для обращения к системе напрямую, выяснялся по MSDN в пять минут. От необходимости что-то писать для линуксов, бог миловал.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 3038
Зарегистрирован: 27.11.2007 16:14:47

Re: Как искать API в Linux

Сообщение sts » 22.12.2023 13:50:35

xchgeaxeax писал(а):И ничего. Механизм переменных окружения не предназначен ни для хранения ни для передачи сетевого имени.

т.е. GetEnvironmentVariable все таки работает верно
sts
постоялец
 
Сообщения: 431
Зарегистрирован: 04.04.2008 12:15:44
Откуда: Тольятти

Пред.След.

Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 2

Рейтинг@Mail.ru