Как вызываются системные вызовы от man 2?

Хорошо, я наконец понял, в чем были проблемы. Мне пришлось переустановить окна в режиме AHCI вместо RAID (это Dell XPS 13 с SSD-накопителем). Затем я уменьшил примерно 100 ГБ, чтобы освободить место для linux ubuntu рядом с окнами, и установил ubuntu с флеш-накопителя. Мне пришлось УБЕДИТЬСЯ, что я подключился к Wi-Fi при установке ubuntu (ранее я пропустил этот шаг), потому что в противном случае он по какой-то причине не добавил бы ubuntu в меню grub при запуске. Итак, есть мое решение на случай, если кто-то сочтет его полезным во время двойной загрузки

2
15.06.2017, 17:40
2 ответа

Для большинства системных вызовов с справочными страницами в разделе 2 справочные страницы фактически описывают оболочки библиотеки C. Исключения обычно упоминаются явно, например gettid , на которые @Sergei Kurenkov ссылается в своем ответе:

ПРИМЕЧАНИЯ Glibc не предоставляет оболочку для этого системного вызова; вызовите его с помощью системного вызова (2).

Аналогично с pivot_root (который не очень полезен для общих приложений), tgkill (который выполняет низкоуровневую функцию pthread_kill). Затем есть readdir , где фактический системный вызов несколько отличается от библиотечной функции:

DESCRIPTION Это не та функция, которая вас интересует. Посмотрите на readdir(3) для интерфейса библиотеки C, соответствующего POSIX. Документы на этой странице голый интерфейс системных вызовов ядра, который заменен гетденты (2).

Обратите внимание, что должна быть какая-то оболочка.Вызовы функций выполняются с использованием соглашений о вызовах C, которые отличаются от соглашений о вызовах интерфейса ядра. Обычные вызовы функций выполняются с помощью ассемблерной инструкции call (или аналогичной), вызовы ядра с помощью syscall или int 0x80 (и это не считая таких вещей, как gettimeofday или getpid в vdso). Компилятору не нужно (необходимо) знать, какие вызовы функций сопоставляются с фактическим вызовом ядра.

Даже с «обычными» системными вызовами оболочка библиотеки C действует несколько иначе, чем простой системный вызов: системные вызовы возвращают коды ошибок в виде различных отрицательных значений (если вы посмотрите на код ядра Linux, вы увидите много возвратов, таких как return -EPERM;). Оболочка библиотеки C превращает все такие возвращаемые значения в -1 и перемещает фактический код ошибки в errno.

2
27.01.2020, 21:53

скомпилированная программа на C никогда НАПРЯМУЮ не вызывает системные вызовы.

Это неправда. Возьмите gettid в качестве примера: http://man7.org/linux/man-pages/man2/gettid.2.html. У него нет оболочки, поэтому вам нужно написать в своей программе что-то вроде (из man: Glibc не предоставляет оболочки для этого системного вызова; вызовите ее с помощью syscall(2). ):

#ifndef WIN32

#include <linux/unistd.h>
#include <sys/syscall.h>
#include <unistd.h>
int thread_gettid(void) {
    return static_cast<int>(syscall(SYS_gettid));
}
#else
int thread_gettid(void) {
    return GetCurrentThreadId();
}
#endif

My понимание выше неверно. Программы могут вызывать системные вызовы без поддержки glibc.

Действительно, может. Он использует системный вызов: http://man7.org/linux/man-pages/man2/syscall.2.html.

Но как тогда brk подключается к программе?

Похоже, brk действительно имеет обертку в glibc, так как в man есть строчка:

The return value described above for brk() is the behavior provided 
by the glibc wrapper function for the Linux brk() system call.

Если это glibc, то почему она не задокументирована в man 3

Я думаю, это потому, что для выделения памяти необходимо использовать malloc:

Избегайте использования brk() и sbrk(): пакет распределения памяти malloc(3) это портативный и удобный способ распределения памяти.

0
27.01.2020, 21:53

Теги

Похожие вопросы