В системах Linux существует четыре основных способа для связи между пространством ядра и пользовательским пространством:
- Конкретным системным вызовом
- Устройством в
/dev
(в случае, с помощью конкретных IOCTLs)
- файл в
/proc
- атрибут файла в
/sys
Использование определенного сценария не рекомендуется сообществом ядра. Существует несколько причин:
- Вряд ли вы нашли «новый» механизм, необходимый большинству устройств Linux.
- Вы можете изменить основную часть ядра (то есть системный вызов таблица)
- Glibc не будет ничего о вашем системном вызове знать, чтобы ваше приложение будет ссылаться на системном вызов по номеру через
syscall()
- системный вызов номер, который вы должны вызвать потенциально изменить на каждом выпуске ядра Linux (потому что в то же время будут добавлены новые официальные системные вызовы)
- вы потенциально будет иметь разное количество системных вызовов для каждой архитектуры, которую вы хотите поддержать
Если вы действительно хочу дд новый системный вызов, изменения в ядро будет что-то выглядит следующим образом:
diff -ur /linux-2.6.15-orig/arch/x86/kernel/syscall_table_32.S
/linux-2.6.15-modified/arch/x86/kernel/syscall_table_32.S
--- /linux-2.6.15-orig/arch/x86/kernel/syscall_table_32.S 2006-03-02 22:18:35.000000000 +0100
+++ /linux-2.6.15-modified/arch/x86/kernel/syscall_table_32.S 2007-11-05 15:15:58.000000000 +0100
@@ -294,3 +294,4 @@
.long sys_inotify_init
.long sys_inotify_add_watch
.long sys_inotify_rm_watch
+ .long sys_mysyscall /* 294 */
diff -ur /linux-2.6.15-orig/arch/x86/include/asm/unistd_32.h
/linux-2.6.15-modified/arch/x86/include/asm/unistd_32.h
--- /linux-2.6.15-orig/arch/x86/include/asm/unistd.h 2006-03-02 22:18:41.000000000 +0100
+++ /linux-2.6.15-modified/arch/x86/include/asm/unistd.h 2007-11-05 15:16:52.000000000 +0100
@@ -299,8 +299,9 @@
#define __NR_inotify_init 291
#define __NR_inotify_add_watch 292
#define __NR_inotify_rm_watch 293
+#define __NR_mysyscall 294
-#define NR_syscalls 294
+#define NR_syscalls 295
/*
* user-visible error numbers are in the range -1 - -128: see
diff -ur /linux-2.6.15-orig/kernel/sys.c /linux-2.6.15-modified/kernel/sys.c
--- /linux-2.6.15-orig/kernel/sys.c 2007-09-24 19:16:49.000000000 +0200
+++ /linux-2.6.15-modified/kernel/sys.c 2007-11-05 16:25:50.000000000 +0100
@@ -1851,3 +1851,10 @@
}
return error;
}
+
+/* System call added */
+asmlinkage long sys_mysyscall(void)
+{
+ printk(KERN_ERR "This is my system call :)\n");
+ return 0;
+}
Обратите внимание, что это только системный вызов печати сообщения о dmesg
. Вероятно, вы захотите использовать copy_to_user()
и copy_from_user()
для обработки данных в/из пользовательского пространства.
Мое предложение состоит в том, что не использует, но вместо этого использует драйвер устройства Linux, который экспортирует символьное устройство на /dev
. Я предлагаю вам изучить книгу Драйверы устройств Linux, 3-е издание от Corbet и Rubini. Это freely available on Internet.
Вопрос «Какие базовые договоренности требуются?» Выходит из области переполнения стека. В сети много примеров добавления системных вызовов в ядро Linux. Попробуйте раскрыть их и вернуться с более сложным вопросом (если вам нужна помощь). – Tsyvarev
Я довольно озадачен количеством людей, которые хотят узнать, как добавить системный вызов. На самом деле это довольно редкая задача, и, вероятно, это будет служить вам. Вместо этого вы должны лучше узнать о символьных устройствах, их различных интерфейсах и интерфейсах sysfs. Кроме того, гарантируется, что функция userpace functionnality всегда будет очень плохой идеей. –
Я узнал, как взаимодействовать с ядром-космос Теперь я смотрю на устройства символов. –