Разработка ядра Linux | страница 85



• Для всех поддерживаемых аппаратных платформ номер системной функции должен быть определен в файле >include/linux/unistd.h.

• Системный вызов должен быть вкомпилирован в образ ядра (в противоположность компиляции в качестве загружаемого модуля[30]). Это просто соответствует размещению кода в каком-нибудь важном файле каталога >kernel/.

Давайте более детально рассмотрим эти шаги на примере функции системного вызова, >foo(). Вначале функция >sys_fоо() должна быть добавлена в таблицу системных вызовов. Для большинства аппаратных платформ таблица системных вызовов размещается в файле >entry.S и выглядит примерно следующим образом.

>ENTRY (sys_call_table)

> .long sys_restart_syscall / * 0 * /

> .long sys_exit

> .long sys_fork

> .long sys_read

> .long sys_write

> .long sys_open /* 5 */

>...

> .long sys_timer_delete

> .long sys_clock_settime

> .long sys_clock_gettime /* 280 */

> .long sys_clock_getres

> .long sys_clock_nanosleep

Необходимо добавить новый системный вызов в конец этого списка:

>.long sys_foo

Нашему системному вызову будет назначен следующий свободный номер, 283, хотя мы этого явно и не указывали. Для каждой аппаратной платформы, которую мы будем поддерживать, системный вызов должен быть добавлен в таблицу системных вызовов соответствующей аппаратной платформы (нет необходимости получать номер системного вызова для каждой платформы). Обычно необходимо сделать системный вызов доступным для всех аппаратных платформ. Следует обратить внимание на договоренность указывать комментарии с номером системного вызова через каждые пять записей, что позволяет быстро найти, какой номер какому системному вызову соответствует.

Далее необходимо добавить номер системного вызова в заголовочный файл >include/asm/unistd.h, который сейчас выглядит примерно так.

>/*

>* This file contains the system call numbers.

>*/

>#define __NR_restart_syscall 0

>#define __NR_exit 1

>#define __NR_fork 2

>#define __NR_read 3

>#define __NR_write 4

>#define __NR_open 5

>...

>#define __NR_mq_unlink       278

>#define __NR_mq_timedsend    279

>#define __NR_mq_timedreceive 280

>#define __NR_mq_notify       281

>#define __NR_mq_getsetattr   282

В конец файла добавляется следующая строка.

>#define __NR_foo 283

В конце концов необходимо реализовать сам системный вызов >foo(). Так как системный вызов должен быть вкомпилорован в образ ядра во всех конфигурациях, мы его поместим в файл >kernel/sys.c. Код необходимо размещать в наиболее подходящем файле. Например, если функция относится к планированию выполнения процессов, то ее необходимо помещать в файл