1. Obsługa urządzeń blokowych.
Komunikacja z urządzeniami wejścia-wyjścia polega na przesyłaniu danych do urządzenia oraz odbieraniu ich. Dostęp do poszczególnych urządzeń następuje poprzez pliki specjalne - blokowe (block devices) lub znakowe (character devices). W urządzeniach blokowych dane są obsługiwane w większych porcjach (w urządzeniach znakowych dostęp do danych jest bajt po bajcie). Wydajna obsługa urządzeń blokowych jest nieodzowna do szybkiego i efektywnego funkcjonowania systemu; urządzeniami blokowymi są na przykład: stacje dyskietek, dyski twarde, cd-rom.
2. Zmniejszenie znaczenia struktury buffer head.
W wersji jądra 2.4 za obsługę blokowych operacji odpowiedzialna była struktura 'buffer head'. Jednak wykorzystanie tej struktury do tego celu, nakładało pewne ograniczenia na wydajność systemu (np. każde żądanie wejścia-wyjścia musiało być dzielone na 512-bitowe fragmenty) - nie było możliwe stworzenie wysokiej klasy podsystemu do obsługi blokowych operacji wejścia-wyjścia. Aby poprawić elastyczność i wydajność, w jądrze 2.6 zastosowano nowy sposób zarządzania blokowymi żądaniami wejścia-wyjścia. Struktura 'buffer head' odpowiada obecnie jedynie za odwzorowanie pomiędzy blokami na dysku a buforami w pamięci - przechowuje informacje potrzebne jądru do wykorzystywania buforów. Do obsługi blokowych operacji wejścia-wyjścia została stworzona nowa struktura - BIO.
3. Struktura BIO.
struct bio {
sector_t
bi_sector;
struct bio
*bi_next; /* request queue link */
struct block_device
*bi_bdev;
unsigned long
bi_flags; /* status, command, etc */
unsigned long
bi_rw; /* bottom
bits READ/WRITE,
* top bits priority
*/
unsigned short
bi_vcnt; /* how many bio_vec's
*/
unsigned short
bi_idx; /* current index
into bvl_vec */
/* Number of segments in this
BIO after
* physical address
coalescing is performed.
*/
unsigned short
bi_phys_segments;
/* Number of segments after
physical and DMA remapping
* hardware coalescing is
performed.
*/
unsigned short
bi_hw_segments;
unsigned int
bi_size; /* residual I/O count
*/
unsigned int
bi_max_vecs; /* max bvl_vecs we can hold */
struct bio_vec
*bi_io_vec; /* the actual vec list */
bio_edn_io_t
*bi_end_io;
ztomic_t
bi_cnt; /* pin count */
void
*bi_private;
bio_destructor_t
*bi_destructor; /* destructor */
};
Struktura BIO zawiera zbiór informacji, w którym jedną z najistotniejszych jest wskaźnik (*bi_io_vec) wskazujący na tablicę struktur bio_vec. Ta tablica reprezentuje segmenty, które tworzą bufor dla danego żądania wejścia-wyjścia, czyli innymi słowy cała tablica opisuje bufor (dzięki wykorzystaniu struktury bio_vec rozmiar struktury BIO jest stały). Dany jest także indeks bi_idx wskazujący na pozycję w tablicy struktur bio_vec. Tak wygląda struktura bio_vec:
struct bio_vec {
struct page *bv_page;
unsigned int bv_len;
unsigned int bv_offset;
};
*bv_page - wskaźnik do strony, na której znajduje się dany segment; bv_len - położenie względem początku strony; bv_offset - długość segmentu;
Struktura BIO (podobnie jak coraz więcej wewnętrznych struktur danych jądra) prowadzi rejestr buforów wykorzystując wskaźniki struct page. Wprowadzenie tej zmiany ma klika konsekwencji istotnych podczas tworzenia sterowników:
Bufory danych dla operacji blokowych mogą być w dowolnym miejscu - zarówno w przestrzeni adresowej jądra, jak i w przestrzeni adresowej procesu. Tak więc nie można nic zakładać o lokalizacji źródeł, bądź miejscu docelowym zapisu danych.
Bufory mogą być w obszarze wysokiej pamięci (HMA).
Blokowe operacje wejścia-wyjścia są, bardziej niż kiedykolwiek, rozproszonymi operacjami zbierającymi dane z wielu buforów rozmieszczonych w różnych miejscach
Na pierwszy rzut oka może się wydawać, że struktura BIO jest bardziej skomplikowana w użyciu niż stare rozwiązanie (struktura buffer head opisywała pojedynczy bufor, a obecnie dane mogą być podzielone na kilka buforów znajdujących się w różnych miejscach na dysku), jednakże BIO jest równie proste w użyciu, a jednocześnie znacznie wydajniejsza.
4. Pliki.
5. Linki
autor: Mateusz Konikowski