PDA

View Full Version : Comunicazione da kernel a userspace


NA01
13-06-2006, 19:26
ho montato un simpatico modulo basato su lsf. il problema ora è che devo comunicare un paio di cose al un demonuccio in userspace...
di usare proc non se ne parla, il povero demonuccio richierebbe di non riuscire a leggere tutto in tempo.
af_unix? o ci sono altre alternative?

ciao!

NA01
14-06-2006, 15:03
uppete!

ilsensine
14-06-2006, 15:48
connector

71104
14-06-2006, 15:50
su Windows è molto più facile :Prrr:

ilsensine
14-06-2006, 15:53
su Windows è molto più facile :Prrr:
Tra un driver di windows e un programma c'è qualcosa di più semplice del connector?

71104
14-06-2006, 22:26
Tra un driver di windows e un programma c'è qualcosa di più semplice del connector? boh, so solo che è + semplice visto che dal programma si fa pure con fopen/fread/fwrite... :p
ed è anche molto versatile perché dal driver si può scegliere il tipo di I/O (direct, buffered, neither) senza che cambi nulla nel programma usermode :rolleyes:

NA01
15-06-2006, 11:29
connector
luminoso come al solito!
un po` meno la documentazione in Documentation/connector , ma mi accontentero` :-D
la parte client sembra molto semplice, ora giochero` un po` con l'esempio.

grazie, ciao!

ilsensine
15-06-2006, 13:26
boh, so solo che è + semplice visto che dal programma si fa pure con fopen/fread/fwrite... :p
Stessa cosa su linux
ed è anche molto versatile perché dal driver si può scegliere il tipo di I/O (direct, buffered, neither) senza che cambi nulla nel programma usermode :rolleyes:
Stessa cosa su linux, per i device per cui ha senso (i block device)

Il problema di NA01 può essere risolto in maniera più semplice, con il connector. Mi chiedevo se sotto windows esistesse qualcosa di simile

ilsensine
15-06-2006, 13:27
luminoso come al solito!
un po` meno la documentazione in Documentation/connector , ma mi accontentero` :-D
la parte client sembra molto semplice, ora giochero` un po` con l'esempio.

grazie, ciao!
Guarda i sorgenti di drivers/connector/cn_proc.c, è un esempio più pratico.

71104
15-06-2006, 14:29
Stessa cosa su linux e il nome del file come viene fuori? su Windows dipende: se la periferica ha un nome o un link simbolico nel branch "\DosDevices" del namespace globale (l'unico branch visibile a Win32) allora il nome da aprire con fopen deve essere semplicemente il nome della periferica preceduto da doppio slash-punto-slash; per esempio: "\\\\.\\C:", "\\\\.\\A:", "\\\\.\\CdRom0", "\\\\.\\Pippo", eccetera.
questo sistema però non è consigliato perché bypassa il sistema di sicurezza del PnP Manager: il driver che crea quei link simbolici deve poi gestirsi da se' la sicurezza di quella periferica associando ad essa un descrittore di sicurezza costruito manualmente.
quando invece la periferica non ha nome ne' link simbolici (cosa consigliata) allora affinché sia accessibile da usermode deve essere stata registrata una device interface, sulle quali però non so quasi nulla ^^
penso che quando registri la device interface, semplicemente il PnP Manager crea un symlink alla periferica e costruisce automaticamente un descrittore di sicurezza che la protegga da accessi non autorizzati (di solito i nomi del PnP Manager sono composti da hash kilometrici, hai presente no? :p); insomma semplicemente vuol dire che il PnP Manager gestisce la sicurezza al posto tuo

Stessa cosa su linux, per i device per cui ha senso (i block device) per quali periferiche invece non ha senso...? :wtf:
su Windows ha senso per tutte...

per "tipo di IO" io intendo semplicemente (su Windows) il modo in cui il programma user mode comunica i suoi dati al driver, che è un modulo caricato nel processo del kernel (il processo System, che ha PID = 8); i tre funzionano così:

bufferizzato - l'IO Manager prima di chiamare l'highest driver nello stack ricopia tutti i dati in un buffer bloccato in memoria di sistema (kernel space, non-paged pool) e quindi "sicuro"; ovviamente è la soluzione più dispendiosa e la si mette in atto solo per periferiche che devono trasferire pochi dati

diretto - il driver deve mappare in memoria di sistema il buffer usermode (soliti trucchetti col paging); il buffer usermode non è considerato sicuro perché nel frattempo un altro thread potrebbe deallocarlo, quindi dopo che tale buffer è stato mappato in kernel space è comunque necessario accedervi dentro un try-catch per evitare schermata blu, o quantomeno chiamare prima la ProbeForRead e ProbeForWrite per vedere se si può ancora leggere/scrivere su quel buffer

neither - uguale a diretto, solo che il kernel garantisce che il thread corrente al momento della chiamata al driver sia lo stesso che ha effettuato la richiesta in userland; di conseguenza non c'è bisogno di mappare il buffer in kernel space per accedervi perché da kernel mode si può tranquillamente accedere allo user space del thread corrente. è comunque bene circondare con try-catch

su Linux sono IDENTICI? :wtf:

chi ha copiato? :D

Il problema di NA01 può essere risolto in maniera più semplice, con il connector. Mi chiedevo se sotto windows esistesse qualcosa di simile esiste qualcosa di più semplice di fopen e compagne? :wtf:
come può essere? sono ridotte all'osso... :wtf:

ilsensine
15-06-2006, 15:24
e il nome del file come viene fuori?
/dev/*

per quali periferiche invece non ha senso...? :wtf:
su Windows ha senso per tutte...
Per i char device, ad esempio. Non hanno in genere un backend di storage (come i dischi, per i quali si utilizzano i block device).

bufferizzato - l'IO Manager prima di chiamare l'highest driver nello stack ricopia tutti i dati in un buffer bloccato in memoria di sistema (kernel space, non-paged pool) e quindi "sicuro"; ovviamente è la soluzione più dispendiosa e la si mette in atto solo per periferiche che devono trasferire pochi dati

diretto - il driver deve mappare in memoria di sistema il buffer usermode (soliti trucchetti col paging); il buffer usermode non è considerato sicuro perché nel frattempo un altro thread potrebbe deallocarlo, quindi dopo che tale buffer è stato mappato in kernel space è comunque necessario accedervi dentro un try-catch per evitare schermata blu, o quantomeno chiamare prima la ProbeForRead e ProbeForWrite per vedere se si può ancora leggere/scrivere su quel buffer

neither - uguale a diretto, solo che il kernel garantisce che il thread corrente al momento della chiamata al driver sia lo stesso che ha effettuato la richiesta in userland; di conseguenza non c'è bisogno di mappare il buffer in kernel space per accedervi perché da kernel mode si può tranquillamente accedere allo user space del thread corrente. è comunque bene circondare con try-catch

su Linux sono IDENTICI? :wtf:

Non identici; le tecniche sono ovviamente differenti, ma puoi ottenere risultati simili.

esiste qualcosa di più semplice di fopen e compagne? :wtf:
come può essere? sono ridotte all'osso... :wtf:
Per il driver utilizzare il connector è molto più semplice di creare un device node.
Al programma userspace, un messaggio inviato da/al kernel tramite il connector è molto simile a un datagramma udp.

71104
15-06-2006, 15:45
/dev/* fico :P
ora capisco la "everything is a file" : )

Per i char device, ad esempio. e che so'? :huh:

comunque leggere e scrivere non è l'unico tipo di I/O che si può effettuare su una periferica su Windows: c'è anche l'API DeviceIoControl, e certe periferiche supportano anche altri tipi (sostanzialmente varianti di device I/O control, notifiche relative ad accendimento/spegnimento/standby, e poca altra roba).

ne approfitto per chiederti una cosa che non sono mai riuscito a capire: che tipo di modello è il kernel di Linux? monolitico? microkernel? microkernel modificato (come Windows)? sapevo che fosse monolitico ma poi un amico che non conosce molto bene questa terminologia mi ha confuso le idee... ^^

ilsensine
15-06-2006, 15:54
e che so'? :huh:
Mentre per i block device sono comuni tutta una serie di necessità di bufferizzazione, readhaead ecc. (fornite automaticamente dal kernel, senza collaborazione del driver), i char device rappresentano quei nodi per i quali non è possibile definire una forma comune. I dispositivi più disparati (ed anche esotici) sono gestiti come char device: l'rtc, i generatori di numeri casuali, la famiglia di driver audio, i driver per nvram, chip i2c ecc. sono char device. Per alcuni non hanno neanche senso le primitive di read/write, essendo gestibili solo tramite ioctl (la tua DeviceIoControl).
Ad un programma la differenza tra char e block device non è molto evidente (un cat /dev/zero funziona come un cat /dev/hda), ma influenza profondamente come è strutturato il driver.

Ci sono molti altri modi di comunicare con un driver; il connector che ho suggerito a NA01 è uno dei più recenti, ed è un derivato di una tecnica più datata chiamata "netlink".

ne approfitto per chiederti una cosa che non sono mai riuscito a capire: che tipo di modello è il kernel di Linux? monolitico? microkernel? microkernel modificato (come Windows)? sapevo che fosse monolitico ma poi un amico che non conosce molto bene questa terminologia mi ha confuso le idee... ^^
Monolitico. E' molto modulare, ma modulare non vuol dire microkernel (immagino sia l'errore che ha commesso il tuo amico).

jappilas
15-06-2006, 16:19
che tipo di modello è il kernel di Linux? monolitico? microkernel? microkernel modificato (come Windows)? sapevo che fosse monolitico ma poi un amico che non conosce molto bene questa terminologia mi ha confuso le idee... ^^
credo che lo si possa considerare ibrido per via della concezione e del modo in cui e' stato sviluppato, ma in effetti nemmeno quello di NT e' un microkernel , sebbene per conciliare eleganza e prestazioni e' stato aggiunto ad un microkernel, un Executive "dotato di tutto", (window management incluso) threaded e formalizzato in termini di API e ABI interne ;)
apparentemente, il metro di paragone piu' comune per distinguere i microkernel dai "macrokernel" e' il range di funzionalita' che vengono fatte assolvere al kernel (task scheduling e basta, scheduling piu' paging e basta, scheduling piu' paging piu' filesystem piu' networking piu' device management e tutti i driver, ecc...), e il numero e livello delle "astrazioni" che il kernel implementa (microkernel puro <=> processi)
mentre quello per distinguere quelli puramente monolitici dagli altri e' il modo in cui nuovi componenti software, per funzionalita' aggiuntive o supporto di corrispettivi nuovi componenti HW, possono essere aggiunti ad un sistema a runtime (se ricompilando il kernel dopo aver aggiunto una patch o marcato attivo un ramo del source tree o aggiungendo un modulo al kernel o cambiando una variabile di configurazione e/o (ri) avviando un proesso userland)
altro metro di paragone e' a livello delle differenze tra le API, dell' invarianza o meno a livello di API e di ABI ... ma in effetti influenza le implementazioni e il behaviour nei casi di cui sopra
tutto AFAIK :stordita: