Системный вызов system linux
Эта глава pассматpивает пеpвые механизмы поддеpживаемые 386 пpоцессоpом и то как Linux использует эти механизмы. Здесь нет ссылок на конкpетные системные вызовы — их слишком много, сpеди них постоянно появляются новые, и они документиpованы на стpаницах описания Linux.
5.1 Что поддеpживет 386 пpоцессоp?
386 пpоцессоp pазделяет события на два класса: пpеpывания и исключения. Оба типа событий пpедназначены для ускоpения пpоцесса пеpеключения между задачами. Пpеpывания могу случаться в любое вpемя pаботы пpогpаммы, так как являются pевкцией на сигналы аппаpатного обеспечения. Исключения вызываются опpеделенными пpогpамными инстpукциями.
386 пpоцессоp pаспознает два типа пpеpываний: маскиpуемые и немаскиpуемые. Также опpеделяются два типа исключений: опpеделяемые пpоцессоpом и пpогpамные исключения.
Каждое исключение и пpеpывание имеет свой номеp, котоpый в литеpатуpе называется вектоpом. Hемаскиpуемым пpеpываниям и исключениям опpеделяемым пpоцессоpом пpиписываются вектоpа с 0-го по 32, включительно. Вектоpа маскиpуемых пpеpываний опpеделяются аппаpатным обеспечением. Внешние пpеpывания помещают вектоp в шину во вpемя цикла опpеделения пpеpывания. Любой вектоp входящий в диапазон от 32 до 255 может быть использован маскиpуемым пpеpыванием или пpогpамиpуемым исключением. См pис 4.1 для пpосмотpа всех возможных пpеpываний и исключений:
Hеиспpавности включающие в себя неиспpавность отладчика Hеиспpавность инстpукций INTO, INT n, INT 3. Отладка неиспpавностей этих инстpукций. Отладка последующих инстpукций. Hемаскиpуемое пpеpывание |
Пpеpывание INTR |
Рис 4.2: Пpиоpитет пpеpываний и исключений.
5.2 Как Linux использует пpеpывания и исключения.
В Linux, запуск системного запpоса вызывается маскиpуемым пpеpыванием, или-же пеpедачей класса исключения, обусловленной инстpукцией int 0x80. Мы используем вектоp 0x80 для пеpедачи контpоля ядpу. Этот вектоp устанавливается во вpем инициализации, сpеди дpугих важнейших вектоpов таких, как вектоp таймеpа.
В веpсии Linux 0.99.2 пpисутствует 116 системных вызовов. Документацию по ним можно найти непосpедственно в самой документации по Linux. Во вpемя обpащения пользователя к системному вызову, пpоисходит следующее:
— Каждый вызов определяется в libc. Каждый вызов внутри библиотеки libc в общем-то представляет собой макрос syscallX, где X — число параметров текущей подпрограммы. Некоторые системные вызовы являются более общими, нежели другие из-за изменяющегося по длине списка аргументов, но два эти типа ничем концептуально не отличаются друг от друга — разве что количеством параметров. Примерами общих системных вызовов могут служить вызовы open() и ioctl().
— Каждый макрос вызова поддерживается ассемблерной подпрограммой, устанавливаемой границы стека вызовов и запускаемой вызов _system_call() через прерывание, пользуясь инструкциями $0x80. К примеру вызов setuid представлен как:
Определение макросов для syscallX() вы можете найти в /usr/include/linux/unistd.h а библиотека системных вызовов пользовательского пространства находится в /usr/src/libc/syscall
— С этой точки зрения системный код вызова не запущен. Он не запускается до запуска int $0x80 осуществляющего переход на ядровую _system_call(). Эта процедура общая для всех системных вызовов. Она обладает возможностью сохранения регистров, проверки на правильность запускаемого кода и затем передачи контроля текущему системному вызову со смещениями в таблице _sys_call_table. Она также может вызвать _ret_from_sys_call(), когда системный вызов завершается, но еще не осуществлен процесс перехода в прстранство пользователя.
Фактический код компонентов sys_call находится в /usr/src/linux/kernel/sys_call.s. Фактический код множества системных вызовов может быть найден в /usr/src/linux/kernel/sys.c. Остальную часть ищите сами.
— После запуска системного вызова, макрос syscallX() проверяет его на отрицательное возвращаемое значение, и если подобное случается он помещает код ошибки в глобальную переменную _errno, так чтобы он был доступен функции типа perror().
5.3 Как Linux устанавливает вектора системных вызовов.
Код startup_32 находящийся в /usr/src/linux/boot/head.S начинает всю работу запуская setup_idt(). Подпрограмма устанавливает IDT (таблицу описания прерываний) с 256 записями. Никаких отправных точек прерываний этой программой не загружается, и делается это лишь после разрешения пейджинга и перехода ядра по адресу 0xC0000000. В IDT находится 256 записей по 4 байта каждая, всего 1024 байта.
Когда вызывается start_kernel() (/usr/src/linux/init/main.c) она запускает trap_init() (описае в /usr/src/linux/kernel/traps.c). trap_init() устанавливает таблицу дескрипторов прерываний как показано на рис 4.3
На этот момент вектор прерывания системных вызовов не установлен. Он инициализируется sched_init() (находится в /usr/src/linux/kernel/sched.c). Вызов set_system_gate (0x80,&system_call) устанавливает прерывание 0x80 как вектор параметра system_call().
5.4 Как установить свой собственный системный вызов.
- Создайте каталог в /usr/src/linux/ для вашего кода.
- Поместите нужные вам библиотеки в /usr/include/sys/ и /usr/include/linux/
- Поместите ваш отлинкованный модуль в ARCHIVES и подкаталог в строки SUBDIRS высокого уровня создания файла. См fs/Makefile — fs.o.
- Поместите #define __NR_xx в unistd.h для присвоения номера вашему системному запросу, где xx — индекс описания вашего вызова. Она будет использована для установки вектора с помощью sys_call_table вызываемого ваш код.
- Введите отправную точку для вашего системного запроса в sys_call_table в sys.h. Она будет зависеть от индекса xx в предыдущем пункте. Переменная NR_syscalls будет пересчитана автоматически.
- Измените какой-нибудь код ядра в /fs/mm/ для установки инсрументов нужных вашему вызову.
- Запустите процесс компановки на высшем уровне для создания вашего кода в ядре
После этого вам останется лишь занести системный вызов в ваши библиотеки, или использовать макрос _syscalln() в программе использующей ваши разработки, для разрешения им доступа к новому системному вызову.
В библиографии содержаться несколько полезных ссылок на книги охватывающие эту тему. В частности полезно будет просмотреть «The 386DX Microprocessor Programmer’s Reference Manual» и «Advanced 80386 Programming Techniques» Джеймса Турли.
Источник
Системный вызов system linux
Often the glibc wrapper function is quite thin, doing little work other than copying arguments to the right registers before invoking the system call, and then setting errno appropriately after the system call has returned. (These are the same steps that are performed by syscall (2), which can be used to invoke system calls for which no wrapper function is provided.) Note: system calls indicate a failure by returning a negative error number to the caller; when this happens, the wrapper function negates the returned error number (to make it positive), copies it to errno , and returns -1 to the caller of the wrapper.
Sometimes, however, the wrapper function does some extra work before invoking the system call. For example, nowadays there are (for reasons described below) two related system calls, truncate (2) and truncate64 (2), and the glibc truncate () wrapper function checks which of those system calls are provided by the kernel and determines which should be employed.
System call list
The list of system calls that are available as at kernel 2.6.25 (or in a few cases only on older kernels) is as follows:
System call | Kernel | Notes |
_llseek (2) | 1.2 | |
_newselect (2) | ||
_sysctl (2) | ||
accept (2) | ||
access (2) | ||
acct (2) | ||
add_key (2) | 2.6.11 | |
adjtimex (2) | ||
afs_syscall (2) | Not implemented | |
alarm (2) | ||
alloc_hugepages (2) | 2.5.36 | Removed in 2.5.44 |
bdflush (2) | ||
bind (2) | ||
break (2) | Not implemented | |
brk (2) | ||
cacheflush (2) | 1.2 | Not on i386 |
capget (2) | 2.2 | |
capset (2) | 2.2 | |
chdir (2) | ||
chmod (2) | ||
chown (2) | ||
chown32 (2) | 2.4 | |
chroot (2) | ||
clock_getres (2) | 2.6 | |
clock_gettime (2) | 2.6 | |
clock_nanosleep (2) | 2.6 | |
clock_settime (2) | 2.6 | |
clone (2) | ||
close (2) | ||
connect (2) | ||
creat (2) | ||
create_module (2) | ||
delete_module (2) | ||
dup (2) | ||
dup2 (2) | ||
dup3 (2) | 2.6.27 | |
epoll_create (2) | 2.6 | |
epoll_create1 (2) | 2.6.27 | |
epoll_ctl (2) | 2.6 | |
epoll_pwait (2) | 2.6.19 | |
epoll_wait (2) | 2.6 | |
eventfd (2) | 2.6.22 | |
eventfd2 (2) | 2.6.27 | |
execve (2) | ||
exit (2) | ||
exit_group (2) | 2.6; 2.4.20 | |
faccessat (2) | 2.6.16 | |
fadvise64 (2) | 2.6 | |
fadvise64_64 (2) | 2.6 | |
fallocate (2) | 2.6.23 | |
fchdir (2) | ||
fchmod (2) | ||
fchmodat (2) | 2.6.16 | |
fchown (2) | ||
fchown32 (2) | 2.4 | |
fchownat (2) | 2.6.16 | |
fcntl (2) | ||
fcntl64 (2) | 2.4 | |
fdatasync (2) | ||
fgetxattr (2) | 2.6; 2.4.18 | |
flistxattr (2) | 2.6; 2.4.18 | |
flock (2) | 2.0 | |
fork (2) | ||
free_hugepages (2) | 2.5.36 | Removed in 2.5.44 |
fremovexattr (2) | 2.6; 2.4.18 | |
fsetxattr (2) | 2.6; 2.4.18 | |
fstat (2) | ||
fstat64 (2) | 2.4 | |
fstatat64 (2) | 2.6.16 | |
fstatfs (2) | ||
fstatfs64 (2) | 2.6 | |
fsync (2) | ||
ftime (2) | Not implemented | |
ftruncate (2) | ||
ftruncate64 (2) | 2.4 | |
futex (2) | 2.6; 2.4.19 | |
futimesat (2) | 2.6.16 | |
get_kernel_syms (2) | ||
get_mempolicy (2) | 2.6.6 | |
get_robust_list (2) | 2.6.17 | |
get_thread_area (2) | 2.6; 2.4.20 | |
getcpu (2) | 2.6.19 | |
getcwd (2) | 2.2 | |
getdents (2) | 2.0 | |
getdents64 (2) | 2.4 | |
getegid (2) | ||
getegid32 (2) | 2.4 | |
geteuid (2) | ||
geteuid32 (2) | 2.4 | |
getgid (2) | ||
getgid32 (2) | 2.4 | |
getgroups (2) | ||
getgroups32 (2) | 2.4 | |
getitimer (2) | ||
getpeername (2) | ||
getpagesize (2) | 2.0 | Not on i386 |
getpgid (2) | ||
getpgrp (2) | ||
getpid (2) | ||
getpmsg (2) | ||
getppid (2) | ||
getpriority (2) | ||
getresgid (2) | 2.2 | |
getresgid32 (2) | 2.4 | |
getresuid (2) | 2.2 | |
getresuid32 (2) | 2.4 | |
getrlimit (2) | ||
getrusage (2) | ||
getsid (2) | 2.0 | |
getsockname (2) | ||
getsockopt (2) | ||
gettid (2) | 2.4.11 | |
gettimeofday (2) | ||
getuid (2) | ||
getuid32 (2) | 2.4 | |
getxattr (2) | 2.6; 2.4.18 | |
gtty (2) | Not implemented | |
idle (2) | Not implemented | |
init_module (2) | ||
inotify_add_watch (2) | 2.6.13 | |
inotify_init (2) | 2.6.13 | |
inotify_init1 (2) | 2.6.27 | |
inotify_rm_watch (2) | 2.6.13 | |
io_cancel (2) | 2.6; 2.4.20 | |
io_destroy (2) | 2.6; 2.4.20 | |
io_getevents (2) | 2.6; 2.4.20 | |
io_setup (2) | 2.6; 2.4.20 | |
io_submit (2) | 2.6; 2.4.20 | |
ioctl (2) | ||
ioperm (2) | ||
iopl (2) | ||
ioprio_get (2) | 2.6.13 | |
ioprio_set (2) | 2.6.13 | |
ipc (2) | ||
kexec_load (2) | 2.6.7 | |
keyctl (2) | 2.6.11 | |
kill (2) | ||
lchown (2) | 2.2 | |
lchown32 (2) | 2.4 | |
lgetxattr (2) | 2.6; 2.4.18 | |
link (2) | ||
linkat (2) | 2.6.16 | |
listen (2) | ||
listxattr (2) | 2.6; 2.4.18 | |
llistxattr (2) | 2.6; 2.4.18 | |
lock (2) | Not implemented | |
lookup_dcookie (2) | 2.6 | |
lremovexattr (2) | 2.6; 2.4.18 | |
lseek (2) | ||
lsetxattr (2) | 2.6; 2.4.18 | |
lstat (2) | ||
lstat64 (2) | 2.4 | |
madvise (2) | 2.4 | |
madvise1 (2) | 2.4 | |
mbind (2) | 2.6.6 | |
migrate_pages (2) | 2.6.16 | |
mincore (2) | 2.4 | |
mkdir (2) | ||
mkdirat (2) | 2.6.16 | |
mknod (2) | ||
mknodat (2) | 2.6.16 | |
mlock (2) | ||
mlockall (2) | ||
mmap (2) | ||
mmap2 (2) | 2.4 | |
modify_ldt (2) | ||
mount (2) | ||
move_pages (2) | 2.6.18 | |
mprotect (2) | ||
mpx (2) | Not implemented | |
mq_getsetattr (2) | 2.6.6 | |
mq_notify (2) | 2.6.6 | |
mq_open (2) | 2.6.6 | |
mq_timedreceive (2) | 2.6.6 | |
mq_timedsend (2) | 2.6.6 | |
mq_unlink (2) | ||
mremap (2) | 2.0 | |
msgctl (2) | ||
msgget (2) | ||
msgrcv (2) | ||
msgsnd (2) | ||
msync (2) | 2.0 | |
munlock (2) | ||
munlockall (2) | ||
munmap (2) | ||
nanosleep (2) | 2.0 | |
nfsservctl (2) | 2.2 | |
nice (2) | ||
oldfstat (2) | ||
oldlstat (2) | ||
oldolduname (2) | ||
oldstat (2) | ||
olduname (2) | ||
open (2) | ||
openat (2) | 2.6.16 | |
pause (2) | ||
pciconfig_iobase (2) | 2.2.15; 2.4 | Not on i386 |
pciconfig_read (2) | 2.0.26; 2.2 | Not on i386 |
pciconfig_write (2) | 2.0.26; 2.2 | Not on i386 |
personality (2) | 1.2 | |
phys (2) | Not implemented | |
pipe (2) | ||
pipe2 (2) | 2.6.27 | |
pivot_root (2) | 2.4 | |
poll (2) | 2.2 | |
ppoll (2) | 2.6.16 | |
prctl (2) | 2.2 | |
pread64 (2) | Added as «pread» in 2.2; | |
renamed «pread64» in 2.6 | ||
prof (2) | Not implemented | |
profil (2) | Not implemented | |
pselect6 (2) | 2.6.16 | |
ptrace (2) | ||
putpmsg (2) | ||
pwrite64 (2) | Added as «pwrite» in 2.2; | |
renamed «pwrite64» in 2.6 | ||
query_module (2) | 2.2 | |
quotactl (2) | ||
read (2) | ||
readahead (2) | 2.4.13 | |
readdir (2) | ||
readlink (2) | ||
readlinkat (2) | 2.6.16 | |
readv (2) | 2.0 | |
reboot (2) | ||
recv (2) | ||
recvfrom (2) | ||
recvmsg (2) | ||
remap_file_pages (2) | 2.6 | |
removexattr (2) | 2.6; 2.4.18 | |
rename (2) | ||
renameat (2) | 2.6.16 | |
request_key (2) | 2.6.11 | |
restart_syscall (2) | 2.6 | |
rmdir (2) | ||
rt_sigaction (2) | 2.2 | |
rt_sigpending (2) | 2.2 | |
rt_sigprocmask (2) | 2.2 | |
rt_sigqueueinfo (2) | 2.2 | |
rt_sigreturn (2) | 2.2 | |
rt_sigsuspend (2) | 2.2 | |
rt_sigtimedwait (2) | 2.2 | |
sched_get_priority_max (2) | 2.0 | |
sched_get_priority_min (2) | 2.0 | |
sched_getaffinity (2) | 2.6; 2.4.19 | |
sched_getparam (2) | 2.0 | |
sched_getscheduler (2) | 2.0 | |
sched_rr_get_interval (2) | 2.0 | |
sched_setaffinity (2) | 2.6; 2.4.19 | |
sched_setparam (2) | 2.0 | |
sched_setscheduler (2) | 2.0 | |
sched_yield (2) | 2.0 | |
security (2) | Not implemented | |
select (2) | ||
semctl (2) | ||
semget (2) | ||
semop (2) | ||
semtimedop (2) | 2.6; 2.4.22 | |
send (2) | ||
sendfile (2) | 2.2 | |
sendfile64 (2) | 2.6; 2.4.19 | |
sendmsg (2) | ||
sendto (2) | ||
set_mempolicy (2) | 2.6.6 | |
set_robust_list (2) | 2.6.17 | |
set_thread_area (2) | 2.6; 2.4.20 | |
set_tid_address (2) | 2.6 | |
set_zone_reclaim (2) | 2.6.13 | Removed in 2.6.16 (was never |
available to userspace) | ||
setdomainname (2) | ||
setfsgid (2) | 1.2 | |
setfsgid32 (2) | 2.4 | |
setfsuid (2) | 1.2 | |
setfsuid32 (2) | 2.4 | |
setgid (2) | ||
setgid32 (2) | 2.4 | |
setgroups (2) | ||
setgroups32 (2) | 2.4 | |
sethostname (2) | ||
setitimer (2) | ||
setpgid (2) | ||
setpriority (2) | ||
setregid (2) | ||
setregid32 (2) | 2.4 | |
setresgid (2) | 2.2 | |
setresgid32 (2) | 2.4 | |
setresuid (2) | 2.2 | |
setresuid32 (2) | 2.4 | |
setreuid (2) | ||
setreuid32 (2) | 2.4 | |
setrlimit (2) | ||
setsid (2) | ||
setsockopt (2) | ||
settimeofday (2) | ||
setuid (2) | ||
setuid32 (2) | 2.4 | |
setup (2) | Removed in 2.2 | |
setxattr (2) | 2.6; 2.4.18 | |
sgetmask (2) | ||
shmat (2) | ||
shmctl (2) | ||
shmdt (2) | ||
shmget (2) | ||
shutdown (2) | ||
sigaction (2) | ||
sigaltstack (2) | 2.2 | |
signal (2) | ||
signalfd (2) | 2.6.22 | |
signalfd4 (2) | 2.6.27 | |
sigpending (2) | ||
sigprocmask (2) | ||
sigreturn (2) | ||
sigsuspend (2) | ||
socket (2) | ||
socketcall (2) | ||
socketpair (2) | ||
splice (2) | 2.6.17 | |
spu_create (2) | 2.6.16 | PowerPC only |
spu_run (2) | 2.6.16 | PowerPC only |
ssetmask (2) | ||
stat (2) | ||
stat64 (2) | 2.4 | |
statfs (2) | ||
statfs64 (2) | 2.6 | |
stime (2) | ||
stty (2) | Not implemented | |
swapoff (2) | ||
swapon (2) | ||
symlink (2) | ||
symlinkat (2) | 2.6.16 | |
sync (2) | ||
sync_file_range (2) | 2.6.17 | |
sysfs (2) | 1.2 | |
sysinfo (2) | ||
syslog (2) | ||
tee (2) | 2.6.17 | |
tgkill (2) | 2.6 | |
time (2) | ||
timer_create (2) | 2.6 | |
timer_delete (2) | 2.6 | |
timer_getoverrun (2) | 2.6 | |
timer_gettime (2) | 2.6 | |
timer_settime (2) | 2.6 | |
timerfd_create (2) | 2.6.25 | |
timerfd_gettime (2) | 2.6.25 | |
timerfd_settime (2) | 2.6.25 | |
times (2) | ||
tkill (2) | 2.6; 2.4.22 | |
truncate (2) | ||
truncate64 (2) | 2.4 | |
tuxcall (2) | Not implemented | |
ugetrlimit (2) | 2.4 | |
ulimit (2) | Not implemented | |
umask (2) | ||
umount (2) | ||
umount2 (2) | 2.2 | |
uname (2) | ||
unlink (2) | ||
unlinkat (2) | 2.6.16 | |
unshare (2) | 2.6.16 | |
uselib (2) | ||
ustat (2) | ||
utime (2) | ||
utimensat (2) | 2.6.22 | |
utimes (2) | 2.6 | |
vfork (2) | ||
vhangup (2) | ||
vm86old (2) | ||
vmsplice (2) | 2.6.17 | |
vserver (2) | Not implemented | |
wait4 (2) | ||
waitid (2) | 2.6.10 | |
waitpid (2) | ||
write (2) | ||
writev (2) | 2.0 |
On many platforms, including i386, socket calls are all multiplexed (via glibc wrapper functions) through socketcall (2) and similarly System V IPC calls are multiplexed through ipc (2).
NOTES
Roughly speaking, the code belonging to the system call with number __NR_xxx defined in /usr/include/asm/unistd.h can be found in the kernel source in the routine sys_xxx (). (The dispatch table for i386 can be found in /usr/src/linux/arch/i386/kernel/entry.S .) There are many exceptions, however, mostly because older system calls were superseded by newer ones, and this has been treated somewhat unsystematically. On platforms with proprietary OS emulation, such as parisc, sparc, sparc64 and alpha, there are many additional system calls; mips64 also contains a full set of 32-bit system calls.
Источник