Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Kernels
 Boot 
 Memory 
 File system
 0.01
 1.0 
 2.0 
 2.4 
 2.6 
 3.x 
 4.x 
 5.x 
 6.x 
 Интервью 
 Kernel
 HOW-TO 1
 Ptrace
 Kernel-Rebuild-HOWTO
 Runlevel
 Linux daemons
 FAQ
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 Secure Programming for Li...6501 
 Linux Kernel 2.6...5278 
 Trees...1112 
 Максвелл 3...1046 
 William Gropp...984 
 Go Web ...953 
 Ethreal 3...921 
 Gary V.Vaughan-> Libtool...911 
 Ethreal 4...908 
 Ext4 FS...898 
 Clickhouse...896 
 Rodriguez 6...896 
 Ethreal 1...888 
 Steve Pate 1...877 
 C++ Patterns 3...858 
 Assembler...845 
 Ulrich Drepper...838 
 DevFS...779 
 MySQL & PosgreSQL...761 
 Стивенс 9...752 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org

The Linux Kernel / David A Rusling

 
 The Linux Kernel
 David A Rusling
 
Данное руководство основывается на версии ядра 2.0.33 .
Hardware Basics
В 1975 году была опубликована схема процессора Altair 8080 . Его можно было купить за $397 и затем прогаммировать на асме . Энтузиасты сразу начали писать софт для него . В 1982 году появилась IBM PC , с процессором Intel 8088 , 64К памяти и CGA-видео-адаптером. В 1983 появилась IBM PC-XT c 10-метровым хардом . Нынешний Pentium Pro основан на том , что при старте использует режим адресации от 8086 . Процессор имеет таймер,который генерирует циклы. За 1 цикл может выполняться не более 1 инструкции. Процессор на 100 мегагерц производит 100,000,000 циклов каждую секунду . Процессор имеет регистры для временного хранения и обработки данных .
Память различается на быструю и медленную . Быстрая память - это кеш , который может быть встроен в процессор . Например , у альфа-процессора имеется 2 кеша - один для данных и один для кода . Различные компоненты взаимодействуют друг с другом с помощью шины . Шины бывают адрессные,контрольные и для данных . Шина данных двунаправленная-она позволяет читать данные из память и загоняь их обратно . Контрольная шина управляет сигналами . Память можно разделить на общую и I/O .
Управление памятью-одна из важнейших функций системы.Памяти всегда не хватает , а жить как-то надо, вот программисты м придумали виртуальную память . Модель виртуальной памяти позволяет манипулировать существующей физической так , что при ее недостатке специальные механизмы позволяют изыскивать память там , где ее по идее не хватает по определению . Виртуальная память может быть больше физической . Каждый процесс имеет свое собственное виртуальное пространство . Виртуальная память может быть расшарена для нескольких экземпляров одного приложения , например bash .
Процессор читает инструкции из памяти и выполняет их , при этом он может читать какие-то данные и сохранять их в память . В виртуальной памяти все адреса виртуальные и переводятся в реальные физические с помощью специальных таблиц . Механизм перевода реализован с помощью страниц памяти . На альфе эти страницы 8-килобайтные, на интеле - 4-килобайтные . У каждой такой страницы есть свой уникальный номер - page frame number - PFN .
Виртуальный адрес разбит на 2 части - собственно адрес и смещение . Первые 11 бит этого адреса есть смещение и все , начиная с 12 бита , и есть сам адрес . Т.е. процессор при чтении виртуального адреса сначала должен разделить его на 2 части , затем переводит виртуальный адрес в физический и затем добавляет смещение - так получается физический адрес . Для этого используются т.н. page tables . У каждого процесса своя собственная page tables . Каждая строка такой таблицы имеет
   специальный флаг для определения того , валиден ли данный адрес 
   физический PFN , соответствующий виртуальному
   информация об access control на чтение/запись
Виртуальный адрес - это его же индекс в его же page table . Если виртуальный адрес засвопен на диск , он грузится , это критическая операция , и в это время должен выполняться какой-то параллельный процесс . В отличие от пользовательских процессов , ядро залинковано напрямую на физические адреса и не имеет виртуальных адресов .
В линуксе 2.0 3-уровневая модель page tables , которая показана на картинке :
Page Table включает в себя PFN - page frame number для Page Table следующего уровня. Процессор берет содержимое level 1 из виртуального адреса , которое фактически является индексом-смещением для page table 1 уровня . Затем процессор делает то же самое для 2 и 3 уровня. В результате из 3-х слагаемых получается адрес реальной адрес физической страницы , к которому добавляется байтовой смещение внутри страницы .
Структура для страницы называется mem_map , и она входит в список структур mem_map_t , который инициализируется при старте системы . Одна mem_map_t описывает 1 физическую страницу . Поля структуры :
  count - число пользователей страницы
  age   - на его основе решается вопрос о своппинге страницы
  map_nr - PFN страницы
При выделении страниц используется алгоритм Buddy . Страницы выделяются блоками , блок кратен 2 . Т.е. выделение блоками возможно для 1,2,4 и т.д. страниц за 1 раз . free_area ищет для этого ресурсы и выделенные в физической памяти pfn сохраняет. Когда загружается пользовательская программа , под нее выделяется виртуальное адресное пространство :
Привязка к виртуальным адресам называется memory mapping . Базовая структура - mm_struct , к которой привязаны все процессы . Когда в память загружается пользовательская программа , она порождает несколько vm_area_struct , из которых одна относится к коду , другая к данным , и т.д.
Когда физической памяти становится недостаточно,Linux должен пытаться освобождать физические страницы. Эта задачу выполняет демон kswapd . Тип этого процесса kernel thread. Он выполняется в режиме ядра и не привязан к виртуальным адресам . Он стартует в kernel init . С определенной периодичностью он проверяет количество свободных страниц . Он ничего не делает , пока это число больше чем free_pages_high . Как только оно становится меньше , этот демон пытается уменьшить число страниц , используемых в системе . Это достигается несколькими путями :
   уменьшение буфера и page cache
   своппинг виртуальных расшаренных страниц
Если число свободных страниц в системе упало ниже free_pages_low , при каждом последующем цикле демон будет пытаться освободить 6 страниц , либо 3 . После освобождения достаточного числа страниц , он засыпает .
Page cache и buffer cache - прежде всего сюда демон смотрит для освобождения памяти. Демон проверяет массив mem_map и проверяет , закеширована ли страница в одном из них. Если ее там нет , она освобождается . Если она присутствует в кеше , она удаляется из кеша и потом освобождается .
Расшаренная память предназначена для меж-процессорного взаимодействия . Ее описывает структура shmid_ds . Процесс описан в vm_area_struct , в котором имеются указатели vm_next_shared и vm_prev_shared .

Процессы

Каждый процесс представлен структурой task_struct , которые собраны в массиве task . Указатель на текущий процесс называется current . Максимальное число процессов для 2.0 - 512 . Поля структуры task_struct :
  1. state - состояние : Running , Waiting , Stopped , Zombie
  2. Scheduling Information -
                               policy
                               priority
                               rt_priority
                               counter
  3. Identifiers - набор уникальных чисел
                   uid - идентификатор пользователя
                   gid - идентификатор группы пользователей
  4. Inter-Process Communication -
  5. Links - в линуксе нет изолированных процессов , всё связано , 
       связи можно посмотреть ,выполнив команду pstree
  6. Times , Timers
  7. File system
  8. Virtual memory
  9. Processor Specific Context -
он используется каждый раз , когда процесс просыпается из спячки и запускается шедулером
Когда процесс выполняет системный вызов , например чтение файла с диска , в этот момент как правило шедулер , выполняя этот вызов , параллельно переключается на другой процесс , а после вызова возвращает управление первому процессу . В 2.0 установлен интервал т.н. time-slice , который равен 200 мс , по истечение которого автоматически происходит переключение на другой процесс . Процессы можно разделить на 2 группы - нормальные и real time . real time имеют более высокий приоритет .
ELF (Executable and Linkable Format) - формат исполняемых файлов,разработанный в юниксе. Такой файл включает код и данные . Статически слинкованный образ линкуется ld . В файл входит таблица ,в которой прописаны виртуальные адреса , по покоторым загружается код . При этом сам образ исполняемого файла в память не загружается . Вместо этого строится древовидная структура vm_area_struct и page table , и по мере исполнения нужные куски подкачиваются . Динамически слинкованные файлы не включают в себя весь код , который прикручивается динамически в run time с помощью ld.so.1, libc.so.1, ld-linux.so.1. При динамической линковке бинарнику нужно больше ресурсов , потому что бинарные page tables существенно разрастаются .
Процессы взаимодействуют между собой и с ядром . В линуксе несколько механизмов такого взаимодействия - Inter-Process Communication (IPC) . Сигналы - наиболее древняя юниксовая форма меж-процессорного взаимодейтвия , имеет асинхронный характер. Сигнал может быть сгенерирован прерыванием , ошибкой , другим процессом . Вызвать список системных сигналов можно командой
            kill -l
 Вот список для 2.0 :
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL
  5) SIGTRAP	 6) SIGIOT	 7) SIGBUS	 8) SIGFPE
  9) SIGKILL	10) SIGUSR1	11) SIGSEGV	12) SIGUSR2
 13) SIGPIPE	14) SIGALRM	15) SIGTERM	17) SIGCHLD
 18) SIGCONT	19) SIGSTOP	20) SIGTSTP	21) SIGTTIN
 22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
 26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO
 30) SIGPWR	
2 сигнала не могут быть проигнорированы никаким процессом : SIGSTOP и SIGKILL . Остальные сигналы процесс может блокировать . Обработка сигналов выполняется последовательно . Число сигналов ограничено размером dword процессора . Все сигналы собраны в массиве sigaction . Для того , чтобы послать сигнал любому другому сигналу , надо иметь рутовые права . Обычный процесс может послать сигнал процессам со своими uid и gid . При генерации сигнала устанавливается бит signal в структуре task_struct.
Второй способ межпроцессорного взаимодействия - пайпы - pipes . Рассмотрим команду :
     ls | pr | lpr
Вывод команды ls передается команде pr , которая в свою очередь , обработав его , передает команде lpr , которая печатает . Пайпы - байтовый поток . Перенаправлением этого потока занимается шелл . Пайп реализован как 2 структуры типа file , одна на чтение , другая на запись . Существуют именованные пайпы , которые хранятся не в памяти , а в файловой системе .
Существует еще один тип взаимодействия между процессами - System V IPC . Он включает в себя очереди и семафоры . Доступ дается на основе аутентификации . Очереди состоят из сообщений , которые могут приходить от нескольких процессов . Очередей может быть несколько , массив очередей называется msgque . Простейшим примером семафора может быть ячейка памяти , которую могут изменять более одного процесса . Изменение этого состояния есть атомарный процесс . Состояние одного процесса может зависеть от состояние семафора и от того , что этот семафор может быть изменен другим процессом . Допустим , есть некий файл данных , с которым в режиме чтение-запись работают много процессов . Чтобы скоординировать доступ к этому файлу , можно использовать семафоры. Основная проблема у семафоров - deadlocks , возникает тогда , когда процесс , работающий с семафором , терпит крах , и состояние семафора не восстанавливается к исходному . Для предотвращения этого служит структура sem_undo , в которой хранятся исходные значения семафоров .

Device Drivers

Каждое периферийное устройство имеет собственный контроллер . Для клавиатуры это SuperIO , для дисков это IDE-контроллер . Каждый контроллер имеет свой собственный регистр CSRs . Работой контролера управляет device driver , который для 2.0 как правило является частью ядра . Драйвер функционирует как обычный файл - его можно открыть , произвести запись . Каждый драйвер представлен в системе device special file , как например /dev/hda . Блочные или дисковые устройства содаются командой mknod . Сетевые устройства создаются после того , как будут обнаружены . Линукс поддерживает 3 типа устройств :
   character - чтение и запись напрямую , без буферизации
   block     - чтение и запись поблочная , порциями по 512 1024 байт 
   network   - работают через сокет-интерфейс
 По функциональности драйвера можно разделить на следующие группы :
   kernel code 
   Kernel interfaces
   Kernel mechanisms and services
   Загрузочные
   Конфигурационные 
Существуют 2 метода опроса драйверов - пулинг - polling - и прерывания . Пулинг использует системный таймер для постоянного контроля . В каталоге /proc/interrupts можно найти частотную таблицу для различных типов прерываний :
  0:     727432   timer
  1:      20534   keyboard
  2:          0   cascade
  3:      79691 + serial
  4:      28258 + serial
  5:          1   sound blaster
 11:      20868 + aic7xxx
 13:          1   math error
 14:        247 + ide0
 15:        170 + ide1
Каждое прерывание имеет свой номер , например у флоппи это 6 . Ядро ведет опрос прерываний в специальном режиме , и если одновременно приходят несколько прерываний , они становятся в очередь .
DMA controller - Direct Memory Access - созданы для того , чтобы передавать от устройств большие обьемы данных с высокой скоростью . Общение с памятью происходит без участия процессора . У контролера есть 8 каналов , у каждого канала есть 16-битный регистр . У ДМА есть несколько особенностей- они работают с физической памятью , а не с виртуальной . Вторая особенность - они работают только с нижними 16 М памяти . Некоторые устройства жестко прикреплены к фиксированным каналам . В линуксе базовая дма-структура называется dma_chan. Драйвер может быть подключен как на этапе загрузки с помощью скриптов , так и после , динамически . Каждый драйвер представлен структурой device_struct в массиве chrdevs . Сетевые устройства получают и посылают пакеты данных . Сетевое устройство представлено структурой device . Их инициализация происходит при загрузке . Пакеты представлены структурой sk_buff , в которой представлены информация :
  Name - /dev/ethN 
  Bus Information
  Interface Flags - IFF_UP , IFF_BROADCAST ...
  Protocol Information - mtu , Family , Type , Addresses
  Packet Queue
  Support Functions
 
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье
paristit
  pase umi dolci
2016-06-01 23:42:35