Facultat d’Informàtica de Barcelona
Dept. d’Arquitectura de Computadors
curs 2024/25-2Q
Pràctiques de laboratori |
Mach i MacOS |
|---|
Tradicionalment, a CASO hem fet el laboratori sobre el microkernel Mach fent servir GNUHurd, i una versió de Debian que s’executa a sobre. A partir del curs 2023/2024-Q2 disposem d’un ordinador Apple Mac mini M2, amb MacOSX, sobre el qual podem fer el mateix estil de laboratori.
Com que MacOSX funciona sobre el Microkernel Mach, és una bona alternativa per fer els mateixos exercicis que els proposats per Debian/GNU Hurd.
Material
-
Els exemples de codi sobre Mach adaptats per MacOSX.
Compte a la màquina
-
Us haurem donat un compte d’usuari a la màquina de l’assignatura amb MacOSX.
Terminal (zsh)
Podeu obrir un terminal, connectant-vos per "ssh". El terminal per defecte té l’intèrpret de comandes zsh. El podeu canviar pel "bash" fent servir
$ chsh -s /bin/bash
Eines de desenvolupament (Xcode)
L’ordinador té instal·lades les eines de desenvolupament (Xcode) amb el gcc i els binutils. També disposa dels compiladors d’Apple (Clang i Clang++ / LLVM) i de l’SDK (Software Development Kit) de MacOSX, que us permetrà desenvolupar aplicacions sobre la interfície de Mach 3.0.
$ export PATH=/opt/homebrew/bin:/opt/homebrew/sbin:$PATH
$ export MANPATH=/opt/homebrew/share/man: # Els ":" són molt importants... per què?
$ gcc-14 --version
$ clang --version
$ gcc --version
$ cc --version
$ g++-14 --version
$ clang++ --version
$ g++ --version
$ c++ --version
$ CC --version
Desenvolupament de programes sobre MacOSX
L’SDK queda instal·lat en el directori:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
I en aquest directori, teniu els "header files" de Mach:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include
Clang/Clang++ sap incloure els fitxers d’include i enllaçar amb les llibreries automàticament.
Tingueu en compte - com ja haureu vist abans :) - que hi ha també els noms "gcc" i "g", que invoquen "clang" i "clang" respectivament, i són més o menys compatibles amb gcc-14 i g++-14 en quan a les opcions de compilació. Per invocar el "gcc" real cal posar-se el PATH apuntant a "/opt/homebrew/bin" i executar "gcc-14".
Informació sobre Mach
Tot i que hi ha algunes diferències, en aquest punt podeu trobar informació sobre Mach a la secció "La interfície de Mach" del document corresponent a GNU Hurd.
Exercicis de la pràctica
Copieu el codi d’exemple que us donem (codi-lab-macos-2025.tar.bz2), on teniu també el Makefile que us permetrà compilar el codi font de tots els exercicis.
-
Comproveu que el programa
proc.cfunciona correctament per l’usuari root, però dóna l’error respecte l’accés al port privilegiat del host si l’executa un usuari no privilegiat (per exemple, si l’executeu des de l’usuari "caso"). -
Quin(s) processador(s) indica que tenim el programa
proc.c? Podeu buscar a<mach/machine.h>els codis deCPU TypeiCPU Subtype, i veure com estan definits els tipus de CPU d’Intel (Penryn, Nehalem…), ARM (… Xscale, …, V8, 64E… quins deuen correspondre als M1 i M2?) i PowerPC (601, …, 620…, 970…).-
Proveu també els següents programes. Quins processadors i quins tipus de processador coneixeu? Podeu obtenir alguna informació sobre els processadors que no coneixeu?
-
processor-types processor-subtypes
-
Expliqueu les altres característiques del processador que mostra
proc.c. Obtingueu-les del fitxer<mach/processor_info.h>; localitzeu-hi l’estructuraprocessor_basic_info. -
Comproveu que el programa
memory-management.cdóna errors al compilar… com els podeu arreglar? (pista: falta una coma (,) a la línia 60). Són clars els missatges d’error que dóna el compilador GCC en aquesta situació? -
Un cop arreglat el problema de la pregunta anterior, comproveu que el programa
memory-management.cfunciona correctament. Aquest programa usahost_processorsivm_mapde forma intercalada, per demanar memòria 8 cops. L’ús deprocessor_infoper demanar memòria queda fora del seu ús habitual, però funciona correctament. Responeu:-
Quanta memòria assigna al procés cada crida a
host_processors? -
Quanta memòria assigna al procés cada crida a
vm_map? -
Quines adreces ens dóna el sistema en cada crida (
host_processorsivm_map)? -
Són pàgines consecutives? (pista: us ajudarà, incrementar el número d’iteracions que fa el programa… per veure la seqüència d’adreces més clara)
-
Quines proteccions podem demanar a l’assignar memòria a un procés Mach? (pista: veieu el fitxer
<mach/vm_prot.h>) -
Canvieu el programa per a que la memòria demanada sigui de només lectura. Quin error us dóna el sistema quan executeu aquesta nova versió del programa?
-
Després, afegiu una crida a
vm_protect (…)per tal de desprotegir la memòria per escriptura i que el programa torni a permetre les escriptures en la memòria assignada. Proveu la nova versió i comproveu que ara torna a funcionar correctament.
-
-
Ara feu servir el programa
vm-regions.cper veure les regions de memòria que té un programa amb enllaçat dinàmic.-
Quantes regions té?
-
N’hi ha algunes que semblin "especials"? Podeu trobar informació sobre elles?
-
Abans d’acabar l’execució el
vm-regionsfa una sèrie de "malloc"s. Podeu determinar en quina regió del programa es demana la memòria pel "malloc"? -
De quina manera podem obtenir la mateixa informació sobre les regions d’un procés en Linux?
-
Podeu executar la versió "estàtica" del
vm-regionsper veure quines regions té? Per què? N’hauria de tenir més o menys?
-
-
[opcional] Feu un nou programa que actuï com un
ps, que llisti les tasks que estan corrent (o que estan aturades) en el sistema. Anomeneu-lompsper aprofitar que ja tenim definida la seva compilació en el fitxerMakefile. -
[opcional] Feu un programa
mtaskque rebi una primera opció[-r|-s]i una llista de processos (pids) i els aturi (-s) o els deixi continuar executant-se (-r), usant les cridestask_suspend/task_resume. Exemples:$ mtask -r 84 105 # fa un task_resume de les tasks que pertanyen als processos 84 i 105 $ mtask -s 58 206 87 # atura l'execució dels processos 58, 206 i 87.
|
Tip
|
Busqueu una crida a MacOSX/Mach que us permeti passar d’un pid al port (task_t) que identifica la task.
|
-
Feu un programa, a partir del fitxer
thread.cque creï un flux (thread_create) i li canviï l’estat (rsp,rip) amb les cridesthread_get_stateithread_set_state, per engegar-lo posteriorment (thread_resume). Trobareu els tipus genèrics (independents de l’arquitectura) relacionats amb el context d’un flux en el fitxer<mach/thread_status.h>. La informació específica de com és l’estat d’un thread en una arquitectura ARM - AARCH64 la trobareu a<mach/arm/thread_status.h>:arm_thread_state64_t(i a<mach/arm/_structs.h:_STRUCT_ARM_THREAD_STATE64), i#defines ARM_THREAD_STATE64(flavor)iARM_THREAD_STATE64_COUNT.
La informació per x86_64, per si voleu fer la mateixa pràctica en un MacOS en l’arquitectura d’Intel,
la trobareu a <mach/i386/thread_status.h>: x86_thread_state_t (i a <mach/i386/_structs.h: _STRUCT_X86_THREAD_STATE64), i #defines x86_THREAD_STATE64(flavor), i x86_THREAD_STATE64_COUNT.
Feu que el flux executi una funció amb un bucle infinit i comproveu amb el 'top' que està consumint processador (el top hauria de dir 99% CPU, pel programa - thread - que es situa a dalt de tot), abans de destruir-lo (thread_terminate).
Ara feu que el thread faci un printf(…). Per què us dóna un segmentation fault? Podeu esbrinar què passa?
|
Tip
|
useu el lldb, i mireu quina instrucció està executant el thread que falla.
|
-
Observeu que en el fitxer
"tsd.h"tenim la definició d’una funció interessant per resoldre el problema de la pregunta anterior. Podeu solucionar el problema?
void _thread_set_tsd_base(void *tsd_base);
|
Tip
|
Mireu també els comentaris que tenim al fitxer thread.c sobre com fer funcionar les variables privades per thread.
|
-
[opcional, aquesta pregunta possiblement només es pot fer amb GNU Hurd i no amb MacOSX] Feu un programa que creï una task (
task_create / task_terminate), i li doni memòria (vm_allocate), per després copiar-li una pàgina de dades (vm_write) Si heu fet la comanda [mps] (exercici 6), comproveu que la vostra task només té la memòria que li heu donat, haurieu d’obtenir una informació com:
virtual size 16384 # si li heu demanat 16KB (4 pàgines) resident size 0
Comproveu que amb la comanda ps aquesta task també es veu:
$ ps -e -o pid,stat,sz,rss,args
PID Stat SZ RSS Args
1670 p 16K 0 ?
-
Feu un programa que accepti un pid i una adreça com a paràmetres, faci un
vm_readde l’adreça donada en el procés donat i mostri la informació obtinguda. Creieu que això mateix es pot fer en UNIX/Linux? I en Windows?
-
[opcional] Feu un programa que creï un procés amb
fork()i faci que pare i fill es comuniquin amb un missatge de Mach, usantmach_msg_send()imach_msg_receive().
-
[opcional] Amplieu el programa [mps] (exercici 7), de forma que també mostri la informació bàsica dels fluxos de cada task.
-
[opcional, aquesta pregunta possiblement només es pot fer amb GNU Hurd i no amb MacOSX] Feu un programa anomenat
cp_mach.cque accepti dos arguments, noms de fitxer. El resultat serà la còpia del fitxer origen (primer argument) al fitxer destí (segon argument). Només haurieu de fer servir crides Mach, sense utilitzaropeniclose.
-
[aquesta comanda ja existeix a MaxOSX] A MacOSX, la comanda
lsmpmostra els mach ports d’un o de tots els processos.-
Proveu com funciona a MacOSX
-
[opcional] Baixeu el {url-lsmp}[codi] d’aquest programa i recompileu-lo en Hurd. Feu els canvis al codi que considereu adients. Aquesta és l’ajuda de la comanda:
-
Usage: lsmp -p <pid> [-a|-v|-h] Lists information about mach ports. Please see man page for description of each column. -p <pid> : print all mach ports for process id <pid>. -a : print all mach ports for all processeses. -v : print verbose details for kernel objects. -j <path> : save output as JSON to <path>. -h : print this help.
|
Important
|
Entregueu: Prepareu els programes i les respostes a les preguntes 2, 3, 4, 5, 6, 9, 10 i 12 per pujar-los al Racó. |