Я смотрю на эту страницу: https://sys.readthedocs.io/en/latest/doc/01_introduction.html
, где объясняется, как glibc выполняет системные вызовы.
В одном из примеров рассматривается код и показано, что последняя инструкция glibc на самом деле выполняет системный вызов (имеется в виду прерывание процессора) написана на ассемблере.. .. Так почему же часть glibc находится в сборке? Есть ли какое-то преимущество в написании этой небольшой части на ассемблере?
Кроме того, общие библиотеки во время выполнения уже скомпилированы в правильный машинный код?
Так в чем же преимущество использования двух разных языков перед компиляцией? Спасибо.
Почему библиотека glibc использует сборку
Ответы (2)
Ответ очень прост: поскольку C не охватывает системные вызовы (поскольку он вообще не охватывает какое-либо физическое оборудование и предпочитает выражать себя в терминах абстрактной машины), нет конструкции C, которую glibc
может использовать для выполнения системы. вызов.
Кто-то может возразить, что компилятор может предоставить своего рода встроенную функцию для этого, но поскольку в Linux glibc на самом деле является частью набора инструментов компилятора (также содержит CRT), на самом деле в нем нет необходимости, glibc может выполнять эту работу.
Кроме того, последнее, но не менее важное: в современных процессорах системный вызов обычно не является прерыванием. Вместо этого это конкретная инструкция (syscall
в x86_64).
syscall
функция, которую могут использовать приложения [обычно предпочтительный способ обхода glibc
для системных вызовов], но glibc
не использует ее внутри. Системный вызов x86 может исходить из [по крайней мере] трех разных машинных инструкций [в зависимости от реализации ОС и того, что поддерживает данная архитектура/модель]: int 0x80
, syscall
или sysenter
. Так что пусть решает библиотека. Кроме того, когда системный вызов возвращается, IIRC, аппаратный флаг x86 carry
устанавливается/сбрасывается в зависимости от ошибки, поэтому каждая библиотека fnc, выполняющая системный вызов, должна обработать это, чтобы правильно установить errno
[и это лучше всего сделать в asm]
- person Craig Estey; 17.08.2018
syscall
; это тоже функция, экспортированная из libc.so
.
- person zwol; 17.08.2018
read
, используя syscall(SYS_read,...)
. Это необходимо для чего-то вроде gettid
, у которого нет функции оболочки glibc.
- person Craig Estey; 17.08.2018
Я хочу ответить на эту часть вашего вопроса:
Кроме того, общие библиотеки во время выполнения уже скомпилированы в машинный код, верно? Итак, в чем преимущество использования двух разных языков перед компиляцией?
SergeyA правильно указывает, что нет какой-либо конструкции C (даже со всеми расширениями GCC), которая заставит компилятор выдать инструкцию syscall
. Это не единственное, что должна делать библиотека C, что просто не может быть написано исключительно на C: реализации setjmp
и longjmp
, makecontext
и setcontext
, код "точки входа", который вызывает main
, "батут", который вы возвращаетесь, когда вы возвращаетесь из обработчика сигнала, и несколько других низкоуровневых битов требуют небольшой ручной сборки. (Упражнение: что у них общего?)
Но есть еще одна причина смешивать язык ассемблера с программой, написанной в основном на C. Это одна из нескольких реализаций memcpy
для x86-64 в glibc. Это 3100 строк написанных от руки макросов на языке ассемблера и препроцессора. То, что он делает, можно выразить четырьмя строчками на языке Си. Зачем кому-то столько хлопот? Скорость. Компиляторы всегда становятся ближе, но им еще не удалось полностью превзойти человеческий мозг, когда дело доходит до выжимания каждого последнего возможного цикла из критического самого внутреннего цикла. (Стоит упомянуть, что в начале 2018 года разработчики glibc потратили уйму времени на замену написанных от руки реализаций функций math.h
на языке C, потому что компиляторы уловили их, а C ремонтопригоднее.)
И все же третий ответ, который не имеет особого отношения к glibc, но часто встречается в других местах, заключается в том, что, возможно, у вас есть два разных языка в вашей программе, потому что каждый из них лучше подходит для решения вашей проблемы. Статистический язык R в основном реализован на C, но множество его математических примитивов написаны (или были, я давно не проверял) на FORTRAN, потому что FORTRAN по-прежнему является языком, на котором думают мастера численных вычислений. Оба C и FORTRAN компилируется в машинный код, и в принципе вы могли бы переписать весь FORTRAN на C, но никто этого не хочет.
restrict
, но в любом случае это хороший момент: научиться думать на C потребует изучения всех подобных вещей. , которые вы должны сделать на C, но не на FORTRAN, поэтому затраты на переключение даже выше, чем кажутся на первый взгляд.
- person zwol; 19.08.2018