tldr:
Если вы вызвали свой системный вызов следующим образом some_syscall(42)
, все, что вам нужно сделать для доступа к 42
, - это позвонить: argint(0, &local_var)
. Это сохраняет 0-й параметр int, 42
, в local_var
.
С argptr вам нужно указать ему адрес указателя и количество байтов памяти, которые вы хотите извлечь. Однако, поскольку указатель в 32-битной архитектуре составляет 4 байта, argint также выполнит эту работу.
Вот общее понимание того, как это работает:
argint
обращается к параметры с некоторой математикой указателя. Он обращается к структуре trapframe процесса, содержащей регистры пользовательского пространства системного вызова. Trapframe сохраняет параметры функции, начиная с регистра esp
. Он добавляет 4, чтобы пропустить пустое слово в стеке из некоторого преобразования, которое, как я считаю, является спецификацией xv6 c. 4*n
означает, что вы можете получить доступ к n-му 4-байтовому параметру после начального адреса.
fetchint
выполняет некоторую проверку ошибок и фактически сохраняет адрес по адресу, указанному этим *ip
указателем.
// Fetch the nth 32-bit system call argument.
int
argint(int n, int *ip)
{
return fetchint((myproc()->tf->esp) + 4 + 4*n, ip);
}
В syscall.c
, syscall()
управляет передачей пользователю возвращаемого значения вашей функции пространства ядра. Он обращается к этому стеку пользовательского пространства, чтобы установить регистр возвращаемого значения процесса eax
на то, что вернул ваш системный вызов. Вот эта строка для справки:
curproc->tf->eax = syscalls[num]();
Этот github иногда очень полезен для понимания xv6: https://github.com/YehudaShapira/xv6-explained/blob/master/Explanations.md#getting -arguments-in-system-calls