Projektuję sterownik urządzenia, który po prostu czyta i zapisuje do bufora znaków. Moje pytanie dotyczy jednak dwóch funkcji w strukturze file_operations
: read
i write
. Naprawdę nie rozumiem, czym naprawdę jest. Wiem, że dla operacji odczytu i zapisu, *offp
jest przesunięcie pliku, co oznacza bieżącą pozycję odczytu/zapisu pliku, jednak nie jestem nawet pewien, co to znaczy pisać lub czytać do/z pliku urządzenia.Zrozumienie loff_t * offp dla file_operations
Z tego, co zebrałem i tak piszę i czytam z mojego urządzenia, to tworzę strukturę, która reprezentuje moje urządzenie, które nazywam my_char_struct
, co pokazano poniżej.
struct my_char_structure{
struct cdev my_cdev;
struct semaphore sem;
char *data;
ssize_t data_size;
unsigned int access_key;
unsigned long size;
};
To jest statyczną strukturę, która jest inicjowana i wskazał, kiedy mój kierowca jest insmod
jako takie.
static dev_t dev_num;
static struct my_char_structure Dev;
int start_mod(void){
//Because we are dealing with a fictitious device, I want
//the driver to create my two devices with arbitrarily
//assigned major numbers.
struct my_char_structure *my_dev = &Dev;
int err;
alloc_chrdev_region(&dev_num, FIRST_MINOR, COUNT, DEVICE_NAME);
sema_init(&(my_dev->sem),1);
cdev_init(&(my_dev->my_cdev), &fops);
my_dev->my_cdev.owner = THIS_MODULE;
my_dev->my_cdev.ops = &fops;// fops is my file operations struct
err = cdev_add(&my_dev->my_cdev, dev_num, COUNT);
if(err<0)
printk(KERN_ALERT "There was an error %d.",err);
printk(KERN_ALERT " insmod to major number %d",MAJOR(dev_num));
return 0;
}
module_init(start_mod);
gdy urządzenie jest otwarte, po prostu zrobić wskaźnik do pliku otwartego do punktu do tej statycznej struktury, która wcześniej skonfigurować podczas module_init(start_mod)
jako takiego ...
int dev_open(struct inode *in_node, struct file *filp){
static struct my_char_structure *my_dev;
my_dev = container_of(in_node->i_cdev, struct my_char_structure, my_cdev);
printk(KERN_ALERT "The device number is %d",iminor(in_node));
if(!my_dev)
printk(KERN_ALERT "something didn't work. my_dev not initialized.");
filp->private_data = my_dev;
return 0;
}
co moje odczytywanie i zapisywanie metod to modyfikowanie początkowej struktury Dev, którą wskazałem przy pomocy moich otwartych plików. Cokolwiek I copy_to_user
z mojej struktury jest tym, co użytkownik uważa za napisany na urządzeniu i czymkolwiek, co użytkownik uważa za napisane. Ale poza zmianą mojej początkowej struktury Dev, idea pozycji pliku lub przesunięcia nie ma sensu, chyba że odnosi się do wskaźnika buforowanej pamięci w jądrze dla jakiejś arbitralnej struktury lub typu. Jest to jedyna interpretacja, którą mam dla przesunięcia pliku ... czy to prawda? Czy to właśnie odnosi się do loff_t *offp
?
write(struct file *filp, const char __user *buff, size_t count, loff_t *offp)
read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
(biorąc pod uwagę moje rozumienie jest poprawne) Gdy niektóre file_operation takich jak odczytu/zapisu nazywa i nie zaszło *offp
osobiście, co jest loff_t * offp początkowo ustawiony?
Jeśli w ostatnim file_operation offp = some_arbitrary_address (ponieważ tak powiedziałem), czy to, co offp byłoby ustawić, gdy ta operacja jest wywoływana ponownie?
Co się stanie, jeśli uruchomię inne operacje file_opens, czy ustawi to, co pozostawiła ostatnia operacja file_operation, czy będzie przechowywać zakładkę z której operacji file_open używał i zastąpić * offp tym, na co plik file_open miał go?
Pojęcie urządzenia char jest dla mnie zbyt abstrakcyjne, gdy wydaje się, że samo urządzenie nie zapisuje nawet informacji takich jak plik, a raczej sterownik, który zapisuje te informacje. Mam nadzieję, że wyjaśniłem moją mglistość i wyjaśnię wszystko, co wydaje mi się niejednoznaczne.
Kiedy więc zmieniam przesunięcie na offset + = bajt_read/write, wskaźnik użytkownika zostanie zmieniony, ale nie zrobi tego automatycznie? Myślę, że to dla mnie trochę wyjaśnia. Czytałem książkę wydania trzeciej wersji sterownika urządzenia linuksowego, którą wszyscy inni czytają jako intro i która miała ten diagram, w którym wskaźnik przesunięcia odwoływał się do jakiejś dziwnej abstrakcji jądra (z braku lepszego słowa), którą nazwali pozycją pliku. Dzięki za pomoc, ten rodzaj wyczyści rzeczy :) –
Tak. (Przypuszczalnie masz na myśli '* offp + = nbytes'.) Zmienna, którą zmieniasz, jest w rzeczywistości rzeczą typu jądro, ale * reprezentuje * przesunięcie wyszukiwania użytkownika. (Lub, w niektórych przypadkach, przesunięcie dostarczone do wywołania "pread" lub "pwrite", lub nawet coś innego, ale najczęściej, przesunięcie użytkownika 'lseek'). To" dziwna abstrakcja jądra ", jak to nazywasz, jest tym, co sprawia, że 'output (prog1; prog2)> działa. Nawiasem mówiąc, w jądrach * BSD istnieje funkcja o nazwie "uiomove", która automatycznie aktualizuje "przesunięcie we/wy użytkownika"; Linux poszedł w drugą stronę. – torek