OSDev

для всех
Текущее время: 29 апр 2024, 11:05

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 30 ]  На страницу Пред.  1, 2, 3
Автор Сообщение
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 01 ноя 2007, 18:15 

Зарегистрирован: 21 сен 2007, 17:24
Сообщения: 1088
Откуда: Балаково
Вспомнил про один свой эксперимент. Это было давно, когда я ещё делал ядро под ДОС, и ещё на Ассемблере. Проблему эффективности чтения с диска я решал так: те страницы из виртуального адресного пространства задачи, в которые надо было грузить данные с диска, отображал на буфер в нижнем мегабайте физической памяти, и делал обмен с диском через DMA без копирования. Страницы из буфера вместе с данными копировались в другое место лишь тогда, когда к диску обращалась другая задача, и если при этом в нижнем буфере не хватало для неё места. Размер буфера, поделённый на страницы, достаточен для одновременной работы нескольких задач. Только алгоритм управления страницами немного сложноватый.
Правда в новой ОС этого пока нет, т.к. переписывать это на Си довольно долго.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 01 ноя 2007, 19:04 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
SII, слишком много слов. Возможно, ты описал все правильно, но в подобном алгоритме даже небольшая неоднозначность в трактовке многого стоит. К тому же, как ты правильно заметил, не следует полагаться на то, что процессор будет всегда работать с буфером быстрее, чем DMA. Здесь тоже нужно выполнять синхронизацию явно. Может, я здесь один такой непонятливый, но мне почему-то всегда казалось, что алгоритм, пусть даже записанный в словесной форме, можно легко преобразовать к более формальному виду. По твоему описанию мне бы пришлось многое трактовать по-своему. Давай попробуем вместе уточнить этот алгоритм.

Chizh, отчасти поэтому я никогда и не отображаю аппаратные дисковые буферы в пространства тех модулей, которые являются инициаторами дисковых операций. Это требует целого ряда дополнительных действий со страницами.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 02 ноя 2007, 19:18 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Phantom-84

Вообще-то спецификации пишут на естественных языках, а не на алгоритмических (на коих их записать попросту невозможно). И "понимабельность" алгоритмов от замены "если" на "if" навряд ли возрастёт. Кроме того, как прикажете описывать такие вещи, как возникновение прерываний, исходное состояние и т.д. и т.п.?

Я набросал макет драйвера FDC, осуществляющего чтение с диска без запрета прерываний; его текст привожу ниже. Естественно, при этом пришлось сделать кучу предположений и умолчаний об особенностях работы ОС.

Код:
// Точка входа по инициализации драйвера
// Вызывается в процессе загрузки ОС

procedure Init;
begin
  InitController;     // Инициализация "железа"
  Buf1Free:= True;    // Оба буфера свободны
  Buf2Free:= True;
end;

// Точка входа по запуску операции ввода-вывода
// ОС вызывает драйвер по этой точке только в том случае, если очередь
// запросов ввода-вывода была пуста или же драйвер вызвал ОС с сообщением
// о завершении ранее начатой операции (через IOEnded)
// Прерывания разрешены (уровень отложенных обработчиков)

procedure NewIORequest(...);
begin
  CheckIORequest;  // Проверка запроса ввода-вывода на корректность
  if ErrorFound then IOEnded(Failure)   // Есть ошибки - операция завершается,
                                        // не начавшись; ОС может повторно
                                        // вызвать NewIORequest для запуска
                                        // следующей операции
  else begin
    SCnt:= ...  // Установка исходного счётчика секторов
    CHS:= ...   // Установка исходного дискового адреса
    StartIO;    // Запуск операции на выполнение (см. ниже)
  end;
end;

// Запуск операции на контроллере и пересылка предыдущего буфера
// Для упрощения рассматривается только операция чтения с дискеты
// Прерывания разрешены (уровень отложенных обработчиков)

procedure StartIO;
begin
  if Buf1Free then
  begin
    Buf1Free:= False;
    StartRead(CHS, Buf1);
    FlushBuffer(Buf2Free, Buf2);
  end else
  begin
    Buf2Free:= False;
    StartRead(CHS, Buf2);
    FlushBuffer(Buf1Free, Buf1);
  end;
end;

// Точка входа в драйвер по прерыванию от FDC
// Прерывания от FDC запрещены (уровень обработчика аппаратного прерывания)
// Предполагается, что регистры сохранены и другие подобные действия,
// общие для любых прерываний, уже выполнены

procedure InterruptHandler;
begin
  GetFDCStatus;       // Считывание состояния FDC, чтобы снять запрос прерывания
  DeferHandling;      // Разрешение прерываний (FDC вызвать их уже не может)
                      // и откладывание обработки до тех пор, пока не закончится
                      // выполнение других отложенных обработчиков
                     
  // Отсюда выполнение продолжается на уровне отложенных обработчиков
  if IOError then     // Если прерывание вызвано ошибкой ввода-вывода
  begin
    ResetController;    // Сброс контроллера, очистка буферов и т.п.
    Buf1Free:= True;
    Buf2Free:= True;
    IOEnded(Failure);   // Вызов ОС с сообщением о неудачном завершении
                        // операции; она может инициировать новую операцию,
                        // вызвав драйвер через StartIO
  end else
  begin
    Dec(SCnt);          // Уменьшение счётчика секторов
    if SCnt = 0 then    // Чтение завершено
    begin
      if Buf1Free then FlushBuffer(Buf2Free, Buf2)  // Копирование последнего
      else FlushBuffer(Buf1Free, Buf1);             // прочитанного буфера
      IOEnded(Successful);   // Операция завершена успешно
    end else
    begin
      Inc(CHS);         // Дисковый адрес следующего читаемого сектора
      StartIO;          // Запуск очередного чтения
    end;
  end;
end;

// Копирование буфера в область памяти задачи
// Прерывания разрешены (уровень отложенных обработчиков)

procedure FlushBuffer(var BufFree : Boolean; Buf : Pointer);
begin
  if BufFree then Exit;
  MoveToUserBuffer(Buf);  // Собственно копирование в буфер пользователя
                          // (его адрес извлекается из запроса ввода-вывода)
  IncUserBufferPtr;       // Передвижение указателя к участку буфера
                          // пользователя для следующего сектора
  BufFree:= True;         // Освобождение сброшенного буфера драйвера
end;


"За кадром" остаётся синхронизация выполнения различных участков кода внутри ОС -- этот вопрос не имеет прямого отношения к вводу-выводу, поскольку относится ко всему ядру в целом. Я использую отложенную обработку прерываний, когда при запрещённых прерываниях выполняется лишь необходимый минимум действий, связанных с аппаратурой, а основная обработка выполняется в так называемых "отложенных обработчиках", которые выполняются строго последовательно (новый отложенный обработчик получает управление только тогда, когда закончится выполнение всех предыдущих отложенных обработчиков). Эта схема использовалась, в частности, в ОСРВ RSX-11 (для PDP-11), откуда перекочевала в VAX/VMS, а из неё -- в Windows NT (разница фактически только в "навороченности" этой схемы в разных ОС, но суть остаётся одной и той же). Если есть необходимость/желание, можно обсудить вопросы синхронизации внутри ядра в отдельной теме.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 03 ноя 2007, 11:02 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
В отложенном обработчике здесь нет необходимости, т.к. перезапускать операцию ч/з в случае ошибки нужно за его пределами, в основном алгоритме. Кстати я внимательно проанализировал твой пошаговый алгоритм и пришел к выводу, что для выписки данных из буфера инициатору запроса запрещать прерывания не нужно, наоборот их лучше разрешить. Далее лучше все-таки использовать цикл с предусловием. К тому же для однообразия, раз уж ты вынес последнюю выписку из буфера за пределы цикла, можно вынести и посылку первой команды перед циклом, тогда необходимость в проверке, свободен ли буфер, внутри цикла вообще отпадет. Можно пойти и обратным путем - добавить в цикле еще одну проверку на необходимость посылки команды, тогда дополнительная выписка за циклом будет не нужна. Но это все мелочи. Вопрос о синхронизации более важен. Сначала мне показалось, что работать с запрещенными прерываниями просто необходимо (они будут разрешаться ядром только на время передачи ему управления - в моей оси драйвер должен сделать wait()), однако на самом деле следующая команда контроллеру не последует, пока не будет выполнена выписка и проанализирован результат текущей команды (естественно, чтобы команда не последовала от другого потока команд, необходимо выполнить предварительную блокировку по занятости - для многозадачной оси это норма).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 03 ноя 2007, 18:10 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Phantom-84

В отложенном обработчике здесь нет необходимости, т.к. перезапускать операцию ч/з в случае ошибки нужно за его пределами, в основном алгоритме

А причём здесь перезапуск операции в случае ошибки? Представьте себе, что без отложенных прерываниях в момент, когда StartIO пересылает один из буферов (т.е. ранее начала операцию, а затем вызвала FlushBuffer, которая ещё выполняется), происходит прерывание по успешному завершению очередной операции, и управление получает InterruptHandler. Та сохраняет состояние FDC, разрешает прерывания и передаёт управление StartIO для запуска очередного чтения -- а запустить-то невозможно, поскольку оба буфера заняты (один ещё не переписан до конца, другой только что заполнен завершившейся операцией). Если же отложенные прерывания используются, то при разрешении прерываний в InterruptHandler дальнейшая работа этого обработчика откладывается, пока не завершит работу предыдущий обработчик -- в данном случае FlushBuffer. И тогда StartIO будет вызван только после того, как один из буферов освободится.

Что же касается видов циклов, местоположения кода, выдающего команды и т.д. и т.п. -- это не принципиальные, а технические моменты, обсуждать их особого смысла нет, ибо не в них суть.

Кстати, работать с запрещёнными прерываниями проще, но в ОСРВ -- недопустимо, поскольку процессор может на слишком продолжительное время "абстрагироваться от окружающей обстановки". Поэтому-то я и использую отложенные прерывания: они не мешают прерываниям аппаратным, а значит, позволяют моментально отреагировать на нечто критическое, но при этом предоставляют простой механизм упорядочивания выполнения кода ядра.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 03 ноя 2007, 19:39 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
Дело в том, что ты всю основную работу выполняешь в отложенном обработчике. Я бы сделал все значительно проще. Основной алгоритм запускался бы как реакция на обращение к драйверу. Внутри цикла порядок выполнения действий был бы такой (если я правильно понял, то именно это ты и писал вначале):

1) запустить команду;
2) здесь я предлагаю разрешить прерывания;
3) выписать данные из неиспользуемого в запущенной команде полубуфера;
4) отдать управление ОС (ждем сигнала о выполнении команды);
5) раз я сам разрешил прерывания, здесь сам их и запрещу (ОС мне вернет флаг IF таким, каким он был до передачи ей управления);
6) теперь можно анализировать результат выполнения операции.

Обработчик прерывания от флоппика только сохраняет результат и посылает сигнал системе возобновить выполнение нашего драйвера в обычном режиме.

Как видно, очередной запуск команды и очередная выписка из буфера будут выпоняться по очереди (если не учитывать ситуацию, когда возникает ошибка), причем первое и второе действия должы всегда выполняться с разными полубуферами (на каждом витке цикла нужно переключать буферы). Получается, что мы просто будем пытаться у ОС забрать время на выполнение очередной выписки, прежде чем ей передать управление. В текущей реализации я сразу после запуска команды передаю управление ОС.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 03 ноя 2007, 20:59 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Phantom-84

Теперь "моя твоя не понимай" :) В частности, как управление попадает на п. 5, если в п. 4 управление было возвращено ОС? И что будет, если в процессе выполнения п. 3 (переписи данных из ранее заполненного буфера) произойдёт прерывание по успешному завершению чтения с дискеты (прерывания-то разрешены в п. 2)?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 03 ноя 2007, 22:35 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
Явно мы привыкли использовать разные синхронизирующие механизмы :) Я экспериментальным путем пришел к самой удачной по моему мнению схеме. Пункт 4 (отдать управление ОС) применительно к моей оси - это обращение к функции ядра wait(), после обращения к которой, как видно из названия, драйвер перейдет в состояние ожидания. Когда произойдет прерывание, обработчик сохранит результат и просигнализирует, чтобы процесс, от имени которого последний раз работал драйвер, перешел в состояние готовности (опять-таки этим займется ядро). Так что управление попадет на пункт 5 после выполнения пункта 4, т.е. спустя какое-то время после возникновения очередного прерывания от флоппика (выполнения последней команды).


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 03 ноя 2007, 22:48 

Зарегистрирован: 28 окт 2007, 18:33
Сообщения: 1418
Phantom-84

Явно мы привыкли использовать разные синхронизирующие механизмы''

Это точно :) На досуге подумаю над альтернативным моему механизмом.

Так что управление попадет на пункт 5 после выполнения пункта 4, т.е. спустя какое-то время после возникновения очередного прерывания от флоппика (выполнения последней команды)''

Если я правильно понял, возникновение прерывания от FDC во время п. 3 приведёт лишь к тому, что вызов wait() в п. 4 не приведёт к реальной остановке драйвера, и он продолжит работать с п. 5? Т.е. что управление на п. 5 в принципе не может попасть до тех пор, пока не будет вызван wait()?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Программирование floppy
СообщениеДобавлено: 03 ноя 2007, 22:56 

Зарегистрирован: 10 май 2007, 11:33
Сообщения: 1206
Да, если сигнал пришел с опережением (например, пока выполнялся пункт 3), драйвер не будет переводиться в состояние ожидания. В этом случае wait() отработает очень быстро.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 30 ]  На страницу Пред.  1, 2, 3

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 8


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB