В настоящее время мы реализуем три простых системных вызова: sys_read
, sys_write
и sys_exit
. Изучив их реализацию, становится понятно, что реализация других системных вызовов не представляет особой сложности.
Реализовать системный вызов в пользовательской программе довольно просто, подобно тому, как мы использовали sbi_call
в операционной системе, нужно только передать параметры в соответствии с правилами. Более того, на этот раз нам даже не нужно ссылаться на какой-либо стандарт, каждый может реализовать свой собственный стандарт для своей операционной системы.
Например, в руководстве по эксперименту номер системного вызова использует кодировку и формат параметров из musl. Однако на самом деле при реализации операционной системы можно свободно настраивать кодировку и форматы параметров, главное, чтобы они соответствовали вызовам в пользовательских программах и интерпретации в операционной системе.
{% label %}Пример кода{% endlabel %}
// musl 中的 sys_read 调用 формата
llvm_asm!("ecall" :
"={x10}" (/* 返回读取长度 */) :
"{x10}" (/* 文件描述符 */),
"{x11}" (/* 读取缓冲区 */),
"{x12}" (/* 缓冲区长度 */),
"{x17}" (/* sys_read 编号 63 */) ::
);
// Возможный формат вызова sys_read
llvm_asm!("ecall" :
"={x10}" (/* текущее время */),
"={x11}" (/* погода сегодня */),
"={x12}" (/* прочитать один символ */) :
"{x20}" (/* sys_read 编号 0x595_7ead */) ::
);
Руководство по эксперименту предоставляет первый скучный формат системного вызова.
В распространённых операционных системах некоторые операции с большими задержками, такие как чтение и запись файлов или сетевое взаимодействие, могут использовать асинхронные интерфейсы. Однако для простоты реализации наши операции чтения и записи являются блокирующими. В sys_read
используется loop
, чтобы гарантировать возврат только после успешного чтения символа.
Если пользовательская программа пытается получить символ с клавиатуры, но в данный момент нет доступных символов, программа будет заблокирована. Задача операционной системы — минимизировать время блокировки потока, занимающее процессорное время, и вместо этого распределить это время между другими исполняемыми потоками. Конкретные методы будут обсуждаться позже в разделе о условных переменных.
Реализация системного вызова в операционной системе похожа на обработку прерываний, у них одинаковый вход, а для разных параметров устанавливаются разные процессы обработки. Чтобы упростить процесс, мы можем разделить результаты обработки системных вызовов на три категории:
x10
, sepc += 4
, и продолжает выполнение текущего context
;x10
и sepc
, но текущий поток должен быть помечен как ожидающий, и другой поток должен быть запущен для выполнения;Как именно реализовать чтение / запись системных вызовов? Здесь мы будем использовать унифицированный интерфейс файлов INode
и его интерфейсы read_at()
и write_at()
, которые могут быть использованы. В следующем разделе будет объяснено, как обрабатывать дескрипторы файлов.
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )