do spisu tresci tematu 7

7.1.5 Tablice rozdzielcze urzadzen

Spis tresci


Wprowadzenie

Tablice rozdzielcze urzadzen blokowych i znakowych sluza do przechowywania informacji o zainstalowanych urzadzeniach w systemie oraz o funkcjach dostepu do tych urzadzen. Wywolanie funkcji systemowej (np. open, close) dla pliku specjalnego przechodzi przez tablice rozdzielcza odpowiadajaca typowi danego pliku.


Struktury danych

Tablice rozdzielcze urzadzen znakowych i blokowych zdefiniowane sa nastepujaco (devices.c):
static struct device_struct chrdevs [MAX_CHRDEV] = {
{ NULL, NULL },
};

static struct device_struct blkdevs [MAX_BLKDEV] = {
{ NULL, NULL },
};

Stale MAX_CHRDEV oraz MAX_BLKDEV sa zdefiniowane w pliku major.h a ich wartosc jest równa 32.

Struktura device_struct ma nastepujaca postac:

struct device_struct
{
        const char *name;                       //nazwa urzadzenia
        struct file_operations *fops            //odpowiednie operacje
};

Oprocz swojego numeru glownego i drugorzednego (MAJOR i MINOR) urzadzenie posiada w Linuxie swoj unikalny numer w polu i_rdev w i-wezle. Zmienna jest typu dev_t (zdefiniowanego jako short).

Funkcje przeliczajace (fs.h):
#define MAJOR(a) (int)((unsigned short)(a) >> 8)
(osiem starszych bitow liczby a)
#define MINOR (a) (int)((unsigned short)(a) & 0xff)
(osiem mlodszych bitow liczby a)
#define MKDEV (a, b) ((int)((((a) & 0xff) << 8) | ((b) & 0xff)))


Funkcje dostepu

Funkcje operujace na tablicach rozdzielczych urzadzen to:

- int get_device_list (char * page)
Na zmienna page zwraca informacjê o zainstalowanych urzadzeniach, wypisuje kolejno (dla urzadzen znakowych i blokowych) numer i nazwe urzadzenia.

- struct file_operations * get_blkfops (unsigned int major)
Dla zadanego wirtualnego urzadzenia blokowego (parametr major) zwraca strukture file operations z tablicy rozdzielczej.

- int register_blkdev (unsigned int major, const char * name, struct file operations * fops)
Instaluje w systemie nowe urzadzenie - wpisuje do tablicy rozdzielczej nowe urzadzenie blokowe o podanych parametrach. Jako liczbe major mozna podac 0, wtedy szuka pierwszego wolnego numeru. Mozliwe bledy: EBUSY (gdy major = 0 i nie ma wolnego miejsca, albo podano juz zajety major), EINVAL (gdy major > MAX_BLKDEV).

- int unregister_blkdev (unsigned int major, const char * name)
Wyinstalowuje urzadzenie - ustawia jego nazwe i wskaznik do operacji na NULL. Blad: EINVAL (gdy zly numer major lub dla podanego numeru nie zgadza sie nazwa).

- int check_disk_change (dev_t dev)
Sprawdza czy zadane urzadzenie o wewnetrznym numerze dev nie zmienilo nosnika (np. wyjecie dyskietki, zmiana plyty CD itp.). Jezeli tak to aktualizuje dane. Dla kazdego urzadzenia jest inna funkcja sprawdzajaca zmiane nosnika - pole check_media_change w strukturze fops.

Dla operacji na urzadzeniach blokowych istnieja odpowiedniki znakowe.

Tablice rozdzielcze sa inicjowane podczas ladowania systemu. Odpowiadaja za to funkcje chr_dev_init() (w mem.c) i blk_dev_init() (w ll_rw_blk.c). Przykladowo:

- chr_dev_init();
        - register_chr_dev(MEM_MAJOR, „mem", &memory_fops);
        - tty_init();
        - lp_init();
        - mouse_init();
        - itp.

Bibliografia

1. Pliki zrodlowe Linuxa: devices.c, major.h.


Autor: Izabela Zielinska