This is an old revision of the document!
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+1 pagini folosind kmalloc.kmalloc_area.NPAGES+1 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.pmap $(pidof mmap-test)
Alt+F2.Alt+F1.