Selfie: syscalls y procesos por dentro
Selfie (Christoph Kirsch y Sara Seidl, Universidad de Salzburgo) es un sistema mínimo y autocontenido de 64 bits, todo en un solo archivo selfie.c. Sirve para ver por dentro todo lo que Stallings describe en abstracto.
| Componente | Qué es | «Self-…» |
|---|---|---|
| starc | compilador de C* (un subconjunto pequeño de C) a RISC-U (un subconjunto de RISC-V) | self-compiling: se compila a sí mismo |
| mipster | emulador de RISC-U en software: una máquina de 32 registros, 0–64 MB de memoria y el ciclo fetch–decode–execute | self-executing: puede ejecutarse a sí mismo |
| hypster | hipervisor: VMs RISC-U que pueden alojar starc, mipster y el propio hypster | self-hosting |
| libcstar | biblioteca C* diminuta | — |
¿Por qué hace falta un emulador? Porque un procesador x86 solo ejecuta su propia ISA. El código RISC-U corre sobre mipster, que a su vez fue compilado con gcc para x86 (./selfie -c prog.c -m 1 compila y ejecuta con 1 MB).
El ciclo completo de una syscall
Sección titulada «El ciclo completo de una syscall»| Capa | Dónde | Rol |
|---|---|---|
| API | hello-world.c | el programador llama a write(fd, buf, n) como a una función cualquiera |
| ABI (wrapper) | emit_write() en selfie.c | pone los argumentos en registros y el número de la syscall en a7, y ejecuta ecall |
| Handler | handle_exception() → handle_system_call() | identifica que la excepción es una syscall y la despacha según a7 |
| Implementación | implement_write() | hace el trabajo, deja el resultado en a0 y avanza el PC |
En tiempo de compilación, starc ve write(...), lo reconoce como un símbolo registrado y emite una secuencia fija:
ld a0, 0(sp) ; fd (y addi sp, sp, 8 tras cada carga)ld a1, 0(sp) ; *bufferld a2, 0(sp) ; sizeaddi a7, zero, 64 ; número de syscall: write = 64ecall ; trap: pasa el control al "kernel" (mipster)jalr zero, 0(ra) ; vuelve al llamador; el resultado está en a0En tiempo de ejecución:
- mipster encuentra
ecally se genera una excepción. handle_exception(context)detecta que es una syscall.handle_system_call(context)leea7y llama aimplement_*.- La implementación escribe el resultado en
a0, incrementa el PC y retornaDONOTEXIT(oEXIT). El planificador decide quién continúa.
Convención de registros (ABI RISC-V): los argumentos van en a0–a7; el número de syscall en a7; el retorno en a0.
Syscalls nativas
Sección titulada «Syscalls nativas»| Syscall | ID | Para qué |
|---|---|---|
read | 63 | leer de un descriptor |
write | 64 | escribir en un descriptor |
openat | 56 | abrir un archivo |
brk | 214 | mover el límite del heap (lo usa malloc) |
exit | 93 | terminar el proceso |
printf no existe como syscall: la biblioteca formatea y termina llamando a write, igual que en Linux.
Añadir una syscall (laboratorio dummy_syscall: retorna n + 2026)
Sección titulada «Añadir una syscall (laboratorio dummy_syscall: retorna n + 2026)»- ID único:
uint64_t SYSCALL_DUMMY_SYSCALL = 23;. Nunca hay que reutilizar 63, 64, 56, 214 ni 93. - Wrapper
emit_dummy_syscall(): crea la entrada en la tabla de símbolos (create_symbol_table_entry(GLOBAL_TABLE, "dummy_syscall", …, PROCEDURE, UINT64_T, 1, …)), carga el argumento ena0, pone el ID ena7, emiteecallyjalr. Hay que registrarlo enselfie_compile(); si no, el compilador no reconoce el nombre. do_ecall(): declarar qué registros lee y escribe:if (a7 == SYSCALL_DUMMY_SYSCALL) write_register(REG_A0);.- Despacho en
handle_system_call()según el ID. implement_dummy_syscall(context):*(get_regs(context) + REG_A0) = valor + 2026;y no olvidar avanzar el PC, porque si no mipster reejecuta elecallpara siempre. Unreturnde C no sirve: los registros simulados viven en un arreglo.
Procesos en Selfie
Sección titulada «Procesos en Selfie»- El PCB es el
context: un arreglo de 32uint64_t(C* no tiene structs). Sus campos sonnextyprev(lista doble), PC, puntero a los registros, tabla de páginas, límites de código, datos y heap y el program break, excepción y página que falló, código de salida, padre y contadores (instrucciones, syscalls, fallos de página). - Tabla de procesos: las listas
used_contexts(doble) yfree_contexts(simple, para reciclar PCBs: object pooling). Se usancreate_context()=new_context()+init_context(), ydelete_context()yfree_context(). - El cambio de contexto:
uint64_t* mipster_switch(uint64_t* to_context, uint64_t timeout) { restore_context(to_context); // carga PC, registros y tabla de páginas del entrante do_switch(to_context, timeout); // current_context = to; arma el timer (quantum) run_until_exception(); // ejecuta hasta un timeout, una syscall o un page fault save_context(current_context); // guarda el estado del saliente return current_context;}- El planificador no existe: el bucle
mipster()tiene literalmente// TODO: scheduler should go herey siempre le devuelve la CPU al mismo contexto (to_context = from_context, conTIMESLICE). Implementar round-robin entre varios contextos fue la tarea del HW2.
| Concepto de Stallings | En Selfie |
|---|---|
| PCB | el arreglo context |
| Crear un proceso | create_context() |
| Tabla de procesos | las listas used_contexts y free_contexts |
| Process switch | mipster_switch(): restore_context → run_until_exception → save_context |
| Timer / quantum | TIMESLICE en do_switch |
| Trap / syscall | ecall → handle_exception → handle_system_call |
Autoevaluación
0/6 correctas · 0 respondidasFuente ·OST-03-Selfie_Syscalls.pdf · Dummy_Syscall_Selfie.pdf · Resumen_Syscalls_Selfie.md · lab2/Resumenes/Selfie-Syscalls/01–05 · hw2/PUNTO_A_SELFIE_PCB.md (selfie.c en código del curso so/selfie)