glibc 2.21 Linux
Переадресация на системный вызов nanosleep
.
glibc является реализацией по умолчанию для C stdlib в большинстве дистрибутивов Linux для настольных компьютеров.
Как это найти: первый рефлекс:
git ls-files | grep sleep
Содержит:
sysdeps/unix/sysv/linux/sleep.c
и мы знаем, что:
sysdeps/unix/sysv/linux/
содержит специфику Linux.
В верхней части этого файла мы видим:
/* We are going to use the `nanosleep' syscall of the kernel. But the
kernel does not implement the stupid SysV SIGCHLD vs. SIG_IGN
behaviour for this syscall. Therefore we have to emulate it here. */
unsigned int
__sleep (unsigned int seconds)
Так что, если вы доверяете комментариям, мы в основном закончили.
Внизу:
weak_alias (__sleep, sleep)
который в основном говорит __sleep
== sleep
. Функция использует nanosleep
через:
result = __nanosleep (&ts, &ts);
После greppingg:
git grep nanosleep | grep -v abilist
мы получаем небольшой список интересных случаев, и я думаю, что __nanosleep
определено в:
sysdeps/unix/sysv/linux/syscalls.list
на линии:
nanosleep - nanosleep Ci:pp __nanosleep nanosleep
это какой-то супер СУХОЙ магический формат, проанализированный как:
sysdeps/unix/make-syscalls.sh
Затем из каталога сборки:
grep -r __nanosleep
Приводит нас к: /sysd-syscalls
, что make-syscalls.sh
генерирует и содержит:
#### CALL=nanosleep NUMBER=35 ARGS=i:pp SOURCE=-
ifeq (,$(filter nanosleep,$(unix-syscalls)))
unix-syscalls += nanosleep
$(foreach p,$(sysd-rules-targets),$(foreach o,$(object-suffixes),$(objpfx)$(patsubst %,$p,nanosleep)$o)): \
$(..)sysdeps/unix/make-syscalls.sh
$(make-target-directory)
(echo '#define SYSCALL_NAME nanosleep'; \
echo '#define SYSCALL_NARGS 2'; \
echo '#define SYSCALL_SYMBOL __nanosleep'; \
echo '#define SYSCALL_CANCELLABLE 1'; \
echo '#include <syscall-template.S>'; \
echo 'weak_alias (__nanosleep, nanosleep)'; \
echo 'libc_hidden_weak (nanosleep)'; \
) | $(compile-syscall) $(foreach p,$(patsubst %nanosleep,%,$(basename $(@F))),$($(p)CPPFLAGS))
endif
Это выглядит как часть Makefile. git grep sysd-syscalls
показывает, что он включен в:
sysdeps/unix/Makefile:23:-include $(common-objpfx)sysd-syscalls
compile-syscall
выглядит как ключевая часть, поэтому мы находим:
# This is the end of the pipeline for compiling the syscall stubs.
# The stdin is assembler with cpp using sysdep.h macros.
compile-syscall = $(COMPILE.S) -o $@ -x assembler-with-cpp - \
$(compile-mkdep-flags)
Обратите внимание, что -x assembler-with-cpp
- это опция gcc
.
Это #define
s параметров, таких как:
#define SYSCALL_NAME nanosleep
, а затем используйте их по адресу:
#include <syscall-template.S>
Ладно, пока я зайду в игру по расширению макросов.
Я думаю, что тогда генерируется файл posix/nanosleep.o
, который должен быть связан со всем.
Linux 4.2 x86_64 наносимерный системный вызов
Использует планировщик: это не занятой сон.
Поиск ctags:
sys_nanosleep
Приводит нас к kernel/time/hrtimer.c
:
SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp,
hrtimer
обозначает таймер высокого разрешения. Оттуда основная строка выглядит так:
hrtimer_nanosleep
do_nanosleep
set_current_state(TASK_INTERRUPTIBLE);
что прервало сон
freezable_schedule();
, который вызывает schedule()
и позволяет другим процессам запускать
hrtimer_start_expires
hrtimer_start_range_ns
- TODO: достигните
arch/x86
временного уровня
Несколько статей об этом: