#c #linux
Вопрос:
Я пишу функцию системного вызова и тестирую ее с помощью модулей ядра.
Это моя процедура:
- соберите ядро (получите mod.ko)
sudo insmod mod.ko
- написать тестовый файл c
во-первых, я узнал, что номер 336 свободен для системного вызова, поэтому я использую 336 в качестве смещения, подключил свою функцию в sys_call_table:
static int __init init_addsyscall(void)
{
printk("My syscall is starting...n");
sys_call_table = (unsigned long *)0xffffffffaae002c0;
printk("sys_call_table: 0x%pn", sys_call_table);
anything_saved = (int(*)(void))(sys_call_table[__NR_syscall]); /* save original one */
orig_cr0 = clear_and_return_cr0(); /* make cr0 writable */
sys_call_table[__NR_syscall] = (unsigned long)amp;sys_mycall; /* change function pointer */
setback_cr0(orig_cr0); /* recover cr0 */
return 0;
}
мой системный вызов-это:
asmlinkage long sys_mycall(unsigned long long num)
{
printk("my call, num = %llu", num);
if (num % 2 == 0)
return num % 1000000;
else
return num % 100000;
}
мой тестовый файл c:
// t.c
#include <sys/syscall.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("%dn",syscall(336, 19030123456));
return 0;
}
Ожидается , что t.c
будет напечатан 123456
, но он напечатает случайное число. Я много раз пытался запустить эту тестовую функцию и каждый раз получал разное возвращаемое значение. Я использую sudo dmesg
для проверки журнала и могу быть уверен, что мой системный вызов вызван, а аргумент системного вызова также не является моим вводом. Более вероятно, что аргумент является случайным числом…
[ 9444.176815] My syscall is starting...
[ 9444.176825] sys_call_table: 0x000000002dac30a7
[ 9448.550544] my call, num: 18446667112225996632
[ 9449.256182] my call, num: 18446667112224440152
[ 9449.966801] my call, num: 18446667112225046360
[ 9453.252192] my call, num: 18446667112225177432
[ 9455.373322] my call, num: 18446667112225308504
Я новичок и не знаю, что здесь происходит, и могу быть уверен, какая информация необходима для анализа. Если вам нужна более подробная информация, просто дайте мне знать.
Комментарии:
1.Во время
printk
вызоваsys_mycall
, почему вы форматируетеunsigned long long
num
использование%d
? Использует ли он другие преобразования , чем обычныеprintf
, или вы должны использовать%llu
дляunsigned long long
? Я не знаком с работой внутри ядра Linux, но: Выsys_mycall
прошлиunsigned long long
проверку ? Известно ли, что он возвращает along
? Какой типsyscall
возвращает значение? Если это along
, как выsys_mycall
возвращаете, почему вы форматируете егоprintf
с%d
помощью, а не%ld
?2. @EricPostpischil
printk
в основном использует то же самое, что и printf (исключения: отсутствие поддержки float, дополнительные модификаторы для%p
формата и поддержка уровня журнала). Правильные спецификаторы в printk описаны здесь .3. @EricPostpischil извините за ошибку. Это небольшая ошибка, потому что я пытаюсь использовать
int
,long
,unsigned long
,long long
иunsigned long long
тестировать свой код. Я неправильно отредактировал его здесь и исправил. На самом деле,unsigned long long
является типом аргумента и возвращает «длинный», потому что он находится в диапазонеlong
(также вint
). Ключевым моментом проблемы является то, что аргумент кажется не тем значением, которое я в него передал(потому что тот же аргумент, другойnum
в функции).