Pentru rezolvarea laboratorului, vom lucra în același director din care pornim mașina virtuală (~/so2/linux/tools/labs
).
Pașii de rezolvare sunt următorii:
Pentru rezolvarea laboratorului trebuie sa activam suportul de netfilter din kernel. In meniul deschis cu make menuconfig
activati optiunea Networking support/Networking options/Network packet filtering framework (Netfilter)
.
Scheletul de laborator este generat din sursele din directorul tools/labs/templates
. Putem genera scheletele pentru toate laboratoarele folosind următoarea comanda:
tools/labs $ make skels
Pentru a genera scheletul pentru un singur laborator, vom folosi variabila de mediu LABS
:
tools/labs $ make clean tools/labs $ LABS=<lab name> make skels
memory_mapping
.
Similar, putem genera și scheletul pentru un singur exercițiu, atribuind valoarea <lab_name>/<task_name>
variabilei LABS
.
tools/labs/skels
.
Comanda make build
compilează toate modulele din directorul skels
.
student@eg106:~/so2/linux/tools/labs$ make build echo "# autogenerated, do not edit " > skels/Kbuild echo "ccflags-y += -Wno-unused-function -Wno-unused-label -Wno-unused-variable " >> skels/Kbuild for i in ./memory_mapping/vmmap ./memory_mapping/kmmap; do echo "obj-m += $i/" >> skels/Kbuild; done ...
Putem copia modulele generate pe mașina virtuală folosind target-ul copy
al comenzii make, atunci când mașina virtuală este oprită.
student@eg106:~/so2/linux/tools/labs$ make copy student@eg106:~/so2/linux/tools/labs$ make boot
Alternativ, putem copia fișierele prin scp
, pentru e evita repornirea mașinii virtuale. Pentru detalii despre folosirea interacțiunea prin rețea cu mașina virtuală citiți Interacțiunea cu mașina virtuală.
Modulele generate sunt copiate pe mașina virtuală în directorul /home/root/skels/<lab_name>
.
root@qemux86:~/skels/memory_mapping# ls kmmap test vmmap root@qemux86:~/skels/memory_mapping# ls vmmap/ vmmap.ko
După pornirea mașinii virtuale QEMU vom putea folosi comenzi în fereastra QEMU (sau în minicom
) pentru a încărca și descărca modulul de kernel:
root@qemux86:~# insmod skels/<lab_name>/<task_name>/<module_name>.ko root@qemux86:~# rmmod skels/<lab_name>/<task_name>/<module_name>.ko
Ctrl+Shift+t
. Cele trei tab-uri de terminal îndeplinesc următoarele roluri:
~/so2/linux/tools/labs
.~/so2/linux/
cu sursele nucleului unde putem folosi Vim și cscope pentru parcurgerea codului sursă.student@eg106-pc:~$ netcat -lup 6666
git pull --rebase
in directorul ~/so2/linux
, pentru a obține ultima versiune a scheletului de laborator.
kmmap/
pentru a crea o mapare a memoriei driver-ului în user-space.kmalloc
.TODO 1
.NPAGES+2
pagini folosind kmalloc
.kmalloc_area
.NPAGES+2
este necesară pentru aliniere.kmalloc_ptr
(variabilă globală) obținută în urma apelului kmalloc
trebuie aliniată la adresa unei pagini.kmalloc_area = (char *)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK);
PG_reserved
al fiecărei pagini cu ajutorul funcțiilor SetPageReserved
(în funcția de inițializare a modulului), respectiv ClearPageReserved
(în funcția de ieșire a modulului).SetPageReserved
și ClearPageReserved
.0xaa
,0xbb
,0xcc
,0xdd
.mmap
pentru driver.pfn
– page frame number).kmalloc_area
) în adresă fizică utilizați virt_to_phys.pfn
.test/
../mmap-test
.matched
.vmmap/
pentru a crea o mapare a memoriei driver-ului în user-space.vmalloc
.TODO 1
.NPAGES
pagini în funcția de inițializare a modulului folosind vmalloc
.vmalloc_area
(variabilă globală).vmalloc
întoarce adrese aliniate la dimensiunea paginii; nu este nevoie de operații suplimentare.PG_reserved
al fiecărei pagini cu ajutorul funcțiilor SetPageReserved
(în funcția de inițializare a modulului), respectiv ClearPageReserved
(în funcția de ieșire a modulului);SetPageReserved
și ClearPageReserved
.0xaa
,0xbb
,0xcc
,0xdd
.mmap
pentru driver.vmalloc
nu sunt fizic contigue.vmalloc_area
) cu câte o pagină și veți obține pentru fiecare adresă virtuală astfel obținută pfn
-ul. vmalloc_area_ptr
pentru parcurgerea spațiului virtual din kernel space.vmalloc_area
.test/
../mmap-test
.matched
.mmap
și cu apeluri de tipul read
și write
.TODO 2
.offset
trimis operației de read/write.test/
../mmap-test 3
.procfs
în care să afișați totalul memoriei mapate de procesul apelant.TODO 3
.procfs
(PROC_ENTRY_NAME
, definit în mmap-test.h
) care va afișa totalul memoriei mapate de procesul care a apelat read-ul pe acel fișier. Folosiți apelul proc_create.mode
folosiți 0
, iar pentru parametrul parent
folosiți NULL
.my_proc_file_ops
.PROC_ENTRY_NAME
folosind remove_proc_entry.my_seq_show
va trebui să:current
de tip struct task_struct *
.vma_iterator
.mm->mmap
.vm_next
al vm_area_struct pentru a parcurge lista de zone de memorie (vma-uri – virtual memory areas).NULL
.vm_start
și vm_end
pentru fiecare structură pentru a deduce dimensiunea totală.printk("%lx %lx\n, ... )
, vm_start
și vm_end
pentru fiecare structură vm_area_struct
.\n
).single_open
puteți folosi NULL
.test/
../mmap-test 4
.sleep
internă).pmap
pentru a vedea mapările testului și a le compara cu cele obținute.cat /proc/$(pidof mmap-test)/maps
Alt+F2
.Alt+F1
.