Реализация syscall в режиме реального времени Debian Wheezy
В образовательных целях я хочу реализовать системный вызов в Debian Wheezy. Я хочу реализовать его на ядре, которое поставляется в пакете linux-image-3.2.0--rt-amd64. Вот обзор того, что я пытался сделать:
Чтобы получить исходный код ядра:
apt-get source linux-image-3.2.0-4-rt-amd64
Из этого я получаю следующие файлы / каталоги, в которых я выполнял:
linux_3.2.41.orig.tar.xz
linux_3.2.41-2+deb7u2.dsc
linux_3.2.41-2+deb7u2.debian.tar.xz
А также:
linux_3.2.41
, который содержит исходный код ядра.
Затем, чтобы сделать необходимые изменения для того, чтобы добавить системный вызов, я в основном следовал этой странице: Как писать системные вызовы в debian / ubuntu
Ниже приводится сокращенная версия приведенных там инструкций, измененная с учетом внесенных мною изменений.+файл 1: linux-x. x. x/vpart_syscalls/vpart_syscalls.c
#include <linux/linkage.h>
#include <linux/kernel.h>
asmlinkage long insert_partition(char*dest, const char* src)
{
printk("<--- the syscall has been called!");
return 0;
}
-
Файл 2: linux-x. x. x/vpart_syscalls/Makefile. Создайте файл Makefile в том же каталоге тестов, который вы создали выше, и поместите эту строку в это:
obj-y := vpart_syscalls.o
-
Файл 3: linux-x. x. x/arch / x86 / kernel/syscall_table_32.Теперь вы должны добавить свой системный вызов в таблицу системных вызовов. Добавьте к файлу следующую строку:
.long insert_partition
-
Файл 4: linux-x.x. x/arch / x86 / include/asm / unistd_32.h
В этом файле имена всех системных вызовов будут связаны с уникальным номером. После последней пары системный вызов-номер добавьте строку
#define __NR_insert_partition 349
Тогда замените значение NR_syscalls, указав общее число системных вызовов (существующее число увеличивается на 1), т. е. В этом случае NR_syscalls должно было быть 338, а новое значение-339.
#define NR_syscalls 350
- файл 5: linux-x. x. x/include / linux / syscalls.h
Добавьте в файл прототип нашей функции.
asmlinkage long insert_partition(int lenTicks, int vpid);
Непосредственно перед строкой #endif в файле.
- файл 6: Makefile в корне исходного каталога.
Откройте файл Makefile и найдите строку, в которой определено ядро-y, и добавьте тест каталога в конец этой строки.
core-y += kernel/ mm/ fs/ test/ vpart_syscalls/
Затем я приступил к построению ядра иным способом, чем описано здесь:
make localmodconfig
make menuconfig (making no changes)
make-kpkg clean
fakeroot make-kpkg --initrd --append-to-version=+tm kernel_image kernel_headers
cd ..
dpkg -i linux-image-3.8.*
dpkg -i linux-headers-3.8.*
Установленное ядро загружается нормально. Я сделал следующую программу c для тестирования syscall:
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
int main(){
printk("Calling the new syscall!n");
int ret = 100;
ret = syscall(349, 1, 2);
printf("call return value: %in", ret);
return 0;
}
Когда я компилирую и запускаю эту программу, я получаю возвращаемое значение -1. Я проверяю сообщения с помощью dmesg, и нет никаких признаков вызова моего printk..
Если кто-нибудь знает, где моя проблема, я был бы очень, очень счастлив! Я должен сказать, что у меня не слишком большой опыт в изменении и построении ядра, но я многое узнал о нем. Я читал книгу Роберта Лав-разработка ядра linux и несколько руководств по веб-сайтам.
1 ответ:
Я думаю, что шаги 3 и 4 могут быть неверны для 64-битных ядер:
File 3: linux-x.x.x/arch/x86/kernel/syscall_table_32.S. File 4: linux-x.x.x/arch/x86/include/asm/unistd_32.h
Есть два файла здесь: http://lxr.linux.no/linux+В3.2.41/арки/х86/ядра/
syscall_64.c 668 2008-12-24 14:26:58 -0800 syscall_table_32.S 8659 2012-01-04 14:55:50 -0800
Первая определяет содержание таблицы системных вызовов в 64-разрядном режиме с помощью файла c-и макро-обман с unistd_64.h
#define __SYSCALL(nr, sym) [nr] = sym, const sys_call_ptr_t sys_call_table[__NR_syscall_max+1] = { .... #include <asm/unistd_64.h> };
Где
asm/unistd_64.h
- это#define __NR_read 0 __SYSCALL(__NR_read, sys_read)
И так далее.
И второй, который вы изменили-для 32-битного режима и написан с использованием файла asm и меток (
.long sys_call_name
).Итак, вы определили syscall для 32-битного режима и используете linux-образ-3.2.0-4-rt-amd64 , который в основном предназначен для"64-битных ПК".
Я думаю, что вы скомпилировали свою тестовую программу как
gcc test.c
, которая по умолчанию работает в 64-битном режиме. Вы можете попробовать-m32
вариант gcc:gcc -m32 test.c
, чтобы получить 32-битное приложение (это будет работать только при наличии правильной кросс-среды для 32-битных сборок) или скомпилировать этот тест на каком-нибудь 32-битном linux.Или другой выбор - сделать шаг "4a": edit
arch/x86/include/asm/unistd_64.h
добавить две строки:#define __NR_insert_partition YOUR_NUMBER __SYSCALL(__NR_insert_partition, insert_partition)
Я не уверен, где и как определяется NR_syscalls для 64bit. Он может быть сгенерирован во время сборки.