2011-02-03 5 views
30

Sto lavorando su un modulo Linux per IA64. Il mio problema attuale è che il driver utilizza le macro PAGE_SIZE e PAGE_SHIFT per l'allocazione della pagina dma. Il problema che sto avendo è che la macchina che compila il driver non è quella necessaria per eseguire il driver. Quindi, se PAGE_SIZE sulla macchina di compilazione è 2^14K e il computer di destinazione è 2^16K, il driver fallisce.Come ottenere la dimensione della pagina del kernel Linux a livello di programmazione

Non voglio trasformare questa domanda in un problema di "best practice" sulla compilazione di moduli su macchine che non sono quelli che eseguono i moduli. Capisco i problemi a riguardo. Quello che ho trovato è che la gente usa principalmente getpagesize() o sysconf (_SC_PAGE_SIZE). Queste due opzioni sono fuori dalle intestazioni del kernel ia64 quindi non posso usarle. C'è un altro modo in cui posso ottenere il runtime PAGE_SIZE?

Opzioni Sto cercando:

  • Leggendo alcune file in/proc?
  • syscall?
  • Un'altra funzione che consente di calcolare PAGE_SIZE per deduzione (ad esempio ORDER, getpageshift, ecc.)?
  • Altro?
+0

Stai dicendo che il 'PAGE_SIZE' è configurabile per l'architettura IA64, e non fisso? Pensavo che "PAGE_SIZE" fosse corretto per una determinata architettura (ad esempio, sempre "4096" per x86). –

+0

IA64 supporta infatti più dimensioni di pagina: http://www.informit.com/articles/article.aspx?p=29961&seqNum=3 – mdiener

risposta

5

Questo è quello che ho finalmente fatto:

  • Re-lavoro il mio modulo corrente di prendere un nuovo parametro modulo chiamato page_shift e utilizzato che per calcolare il PAGE_SIZE (PAGE_SIZE = 1 << PAGE_SHIFT)
  • Creato un involucro modulo loader che ottiene la corrente sistema PAGE_SHIFT utilizzando l'API getconf da libc. Questo wrapper ottiene lo spostamento corrente della pagina di sistema e lo passa come parametro del modulo.

In questo momento il modulo viene caricato su diverse architetture con PAGE_SIZE diversi senza problemi.

+0

Domanda noob. Potresti spiegare un po 'di più su wrapper che usa l'API getconf? Voglio dire, hai chiamato comando getconf all'interno della funzione popen() o qualcosa del genere. Un po 'più di luce sarà molto apprezzato. –

6

Se si sta tentando di creare un modulo del kernel, è necessario disporre almeno delle intestazioni del kernel configurate per il kernel su cui verrà eseguito il modulo. Quelli definiranno le macro delle dimensioni della pagina che ti servono. Se non hai le intestazioni configurate correttamente, il kernel rifiuterà di caricare il tuo modulo.

E non c'è niente di sbagliato nel compilare un modulo su una macchina per eseguirne un'altra, anche se si tratta di un'architettura diversa. Hai solo bisogno di costruire contro il corretto sorgente del kernel.

+0

Non si tratta di un problema relativo alle origini del kernel. Riguarda il caricamento di un modulo compilato su una macchina, per l'esecuzione in un'altra macchina (entrambi hanno la stessa versione del kernel ma sono configurati in modo diverso). Non desidero ricompilare la nuova configurazione perché PAGE_SIZE è cambiato. Sto cercando di ottenere quel parametro dal kernel come API, non come MACRO (che viene risolto in fase di compilazione). – Freddy

+0

<< E non c'è niente di sbagliato nella compilazione di un modulo su una macchina per l'esecuzione su un'altra, anche se si tratta di un'architettura diversa. Hai solo bisogno di costruire contro il corretto sorgente del kernel. ........... ESATTAMENTE IL PUNTO – kumar

+0

PAGE_SIZE è molto fondamentale e richiesto per un modulo durante la costruzione del modulo stesso .. – kumar

0

Temo che sia impossibile fare come la dimensione della pagina è qualcosa definito come parte del kernel. La conoscenza della dimensione della pagina è richiesta nel caso di toolchain che usi anche per compilare il modulo del kernel.

Quindi, con l'architettura del kernel corrente, è impossibile farlo.

17

Un metodo approssimativo è quello di leggere e verificare /proc/meminfoMapped dimensioni (sulla mia suoi 52544 kB fin d'ora) e quindi controllare nr_mapped a /proc/vmstat (sulla mia propria 131136 fin d'ora). Finalmente PAGE_SIZE = Mapped/nr_mapped. A volte questo ti dà un valore preciso (come nell'esempio corrente che ho citato) e qualche volta è approssimativo ma molto vicino. Spero che questo aiuti!

42

Provare a utilizzare l'utilità getconf, che consente di recuperare facilmente le dimensioni della pagina.

getconf PAGESIZE 
+1

Non penso che questo risponda alla domanda dell'OP, ma è un'informazione utile poiché sysconf (_SC_PAGESIZE) sembra restituire 4K su linuxia64 (mentre mprotect fallisce su una pagina non allineata su un limite di 16K). –

0

Si potrebbe semplicemente eseguire un test, solo mmap un file con offset diversi e vedere quale fallire. Potrebbe essere fastidioso in un modulo del kernel, ma forse ci sono altri test come quello che potresti usare.

1

Un modo per trovare la dimensione della pagina è ottenerlo dagli smaps di un processo.

Ad esempio:

cd /proc/1 
cat smaps | grep -i pagesize 

KernelPageSize:  4 kB 
MMUPageSize:   4 kB