Вы находитесь на странице: 1из 70

Sistemas Operativos

Capítulo 2 El Kernel
Prof. Javier Cañas R.
Estos apuntes están tomados en parte del texto:
“Operating System: Principles and Practice” de T.
Anderson y M. Dahin
Puntos Principales
•Concepto de Proceso
‣ Un proceso es una abstracción del SO para ejecutar un
programa con privilegios limitados.
‣ Privacidad: Los datos sólo son accesibles a usuarios
autorizados.

•Modo dual de operación: usuario vs. kernel


‣ Modo kernel: ejecución con todos los privilegios.
‣ Modo usuario: ejecución con privilegios restringidos.

•Cambio de modo seguro


‣ ¿Cómo se pueden conmutar los modos?
Temario
1. El Concepto de Proceso

2. Modo Dual de Operación

3. Memoria y Direcciones Virtuales

4. Interrupciones

5. Llamadas al Sistema

6. Booteo del SO

7. Máquinas Virtuales
Desafío: Protección

• ¿Cómo ejecutar código con privilegios


restringidos?
‣ Puede pasar que el código tiene errores o puede ser malicioso

• Ejemplos
‣ Un script corriendo en un web browser.
‣ Un programa recién descargado de Internet.
‣ Un programa recién escrito pero no probado aún.
1 El Concepto de Proceso Physical
Memory

Machine
Instructions

Data
Process
Operating Heap
Executable
Edits Compiler System Copy
Source Image: Stack
Code Instructions
and Data

Machine
Instructions
Operating
Data System
Heap Kernel
Stack
Concepto de Proceso
• Proceso: instancia de un programa, corriendo con
derechos limitados

• Process Control Block PCB: estructura de datos del


SO que permite mantener el “estado” de un proceso

• Un proceso tiene dos partes


‣ Thread: secuencia de instrucciones dentro de un proceso
- Un proceso puede tener de 1 a n threads
- Un thread se llama también “proceso liviano”
‣ Espacio de direcciones: conjunto de derechos de un proceso
- Memoria a la cual el proceso puede accesar
- Otros permisos: archivos, procedimientos etc.
2 Modo Dual de Operación

• Experimento de pensamiento: ¿Cómo se puede


implementar la ejecución con privilegios limitados?
‣ Ejecutar cada instrucción en un simulador.
‣ Si la instrucción se permite, ejecutarla, sino, parar el proceso.
‣ Este es el modelo básico de Javascript.

• ¿Cómo podemos hacer más rápido?


‣ ¿ejecutar el código directamente en la CPU?
Soporte de HW: Modo dual
• Modo kernel
‣ Ejecución con todos los privilegios del HW.
‣ Read/write a cualquier dirección de memoria, acceso a
cualquier dispositivo de E/S, read/write a cualquier sector de
disco, enviar y leer cualquier paquete de datos.

• Modo usuario
‣ Privilegios restringidos.
‣ Sólo aquellos concedidos por el kernel del SO

• En la arquitectura x86, el modo está en el registro


EFLAG
Modelo simple de CPU
Branch Address

CPU
New PC Program Instructions
Select PC
Counter Fetch and
Execute

opcode
Modelo de CPU con Modo
Dual
Branch Address

CPU
New PC Program Instructions
Select PC
Handler PC Counter Fetch and
Execute

Select
New Mode
Mode
Mode

opcode
Soporte de HW para
Proteger Aplicaciones
• Instrucciones privilegiadas (Modo Dual)
‣ Disponibles para el kernel.
‣ No disponibles en el código de usuario.

• Límites en acceso a memoria


‣ Prevenir que el código usuario sobrescriba el kernel

• Timer
‣ Prevenir que código usuario impida el acceso de otras
aplicaciones al procesador.

• Modo seguro de conmutar los dos modos


Quiz

• Ejemplos de instrucciones privilegiadas

• ¿Qué pasa si un programa usuario intenta ejecutar


una instrucción privilegiada?
3 Memoria y Direcciones
Virtuales
Processor’s View Implementation Physical
Memory

Virtual Base
Memory Base
Virtual Virtual Physical
Address Address Address
Processor Processor

Base+
Bound
Bound

Raise
Exception

Protección de memoria
Hacia las Direcciones
Virtuales

• ¿Qué problema existe con el par de registros Base


y Límite (bound)?
Direcciones Virtuales
• Direcciones virtuales se convierten en direcciones
físicas a través de una tabla.

• La tabla se actualiza sólo por el kernel

Translation Box

yes Physical Address


Virtual Address ok?

no Physical
Processor Memory

raise exception

Instruction fetch or data read/write (untranslated)


Layout de espacio virtual
• Al layout típico de un proceso, habría que agregar
código compartido con otros procesos, bibliotecas
dll, archivos mapeados en memoria….
Virtual Addresses Physical
(Process Layout) Memory

Code
• La conversión de direcciones se hace
Code
por hardware usando una tabla Data
• El kernel activa esta tabla Data
Heap

Heap

Stack

Stack
Ejemplo

• El siguiente código se utiliza para ver si un SO


tiene memoria virtual. Se corren varias instancias
del mismo programa. ¿Cómo se sabe si tiene
memoria virtual?
/*virtual_mem_test.c/
#include <stdio.h>
#include <unistd.h>
static unsigned int staticVar = 0; // a static variable
int main() {
unsigned int localVar = 0; // a procedure local variable

staticVar += 1; localVar += 1;

sleep(10); // sleep causes the program to wait for x seconds


printf ("static address: %p, value: %d\n", &staticVar, staticVar);
printf ("procedure local address: %p, value: %d\n", &localVar, localVar);
}
En Linux:
$ gcc virtual_mem_test.c -o virtual_mem_test
$ ./virtual_mem_test &
[1] 6090
$ ./virtual_mem_test &
[2] 6091
$ ./virtual_mem_test &
[3] 6092
$ static address: 0x804a028, value: 1
procedure local address: 0xbfc2aaac, value: 1
static address: 0x804a028, value: 1
procedure local address: 0xbff8293c, value: 1
static address: 0x804a028, value: 1
procedure local address: 0xbfd6972c, value: 1

[1] Salida 46 ./virtual_mem_test


[2]- Salida 46 ./virtual_mem_test
[3]+ Salida 46 ./virtual_mem_test
4 Interrupciones
• Las interrupciones son eventos que requieren la
atención del kernel.

• Si bien cualquier evento (excepciones) que


requiera atención del kernel se denomina
interrupción, éstas se clasifican en: interrupciones,
excepciones y llamadas al sistema.

• Las interrupciones son asincrónicas respecto a la


ejecución de instrucciones del programa. Las
excepciones y llamadas al sistema son sincrónicas.
Ejemplo de Interrupciones
• Causas de interrupciones pueden ser por
ejemplo:
‣ Oprimir teclas (Ctrl -C por ejemplo)
‣ Disco terminó de transferir bloques de datos
‣ Timer
‣ Llegó un paquete por la red
‣ Batería baja
…Interrupciones
• Elementos
‣ El Vector de Interrupciones
‣ El Stack de Interrupciones del Kernel
‣ PSW: Processor Status Word. Registro de HW con
interrupciones activas

• Procesos relacionados con interrupciones


‣ Enmascaramiento.
‣ Transferencia de control atómica (no interrumpible)
‣ Reactivación transparente de un proceso
whatever actions are needed. In the example we have been using, the handler de-
termines which I/O module generated the interrupt and may branch to a program
that will write more data out to that I/O module. When the interrupt-handler rou-
tine is completed, the processor can resume execution of the user program at the
Ciclo de instrucción con
point of interruption.
It is clear that there is some overhead involved in this process. Extra instructions
must be executed (in the interrupt handler) to determine the nature of the interrupt

interrupción
and to decide on the appropriate action. Nevertheless, because of the relatively large
amount of time that would be wasted by simply waiting on an I/O operation, the
processor can be employed much more efficiently with the use of interrupts.

Fetch stage Execute stage Interrupt stage

Interrupts
disabled
Check for
Fetch next Execute interrupt;
START
instruction instruction Interrupts initiate interrupt
enabled handler

HALT

Figure 1.7 Instruction Cycle with Interrupts


El Vector de Interrupciones
• Tabla manejada por el kernel. Normalmente en
direcciones bajas de memoria. Contiene punteros
a códigos que se ejecutan ante diferentes eventos.
Processor Interrupt
Register Vector kernel memory

handleTimerInterrupt() {
...
}

handleDivideByZero() {
...
}

handleSystemCall() {
...
}
Undefined 11011

Interrupt (IRQ) 10010


Ejemplo: Vector de
Fast Interrupt (FIQ) 10001

Interrupciones ARM
Table 6.14 Exception vector table

Exception Address Mode


Reset 0x00 Supervisor

Undefined Instruction 0x04 Undefined

Supervisor Call 0x08 Supervisor

Prefetch Abort (instruction fetch error) 0x0C Abort

Data Abort (data load or store error) 0x10 Abort

Reserved 0x14 N/A

Interrupt 0x18 IRQ

Fast Interrupt 0x1C FIQ

a High power-up, the processor branches to address 0x00000000. Each excep-


ch the
Transferencia de control por
interrupción
User Program Interrupt handler

Interrupt vector

i+1
Interrupción
i

1
0
Ejemplo: trap de I/O
read(int fileDescriptor, void *buffer, int numBytes)

Salvar user PC!


PC = trap handler address!
Entrar modo kernel!
Modo$usuario$
Modo kernel!
trap handler!
Salvar estado de App! PC = saved PC
Verificar número de syscall! Entrar modo usuario
Encontrar sys_read( ) handler en vector de
interrupción!
sys_read( ) kernel routine!
Verificar argumentos!
Iniciar lectura!
Ejegir un proceso para correr!
Fijar valores de retorno!
Restaurar el estado de la App!

ERET instrucción
El Timer
• Dispositivo de hardware que periódicamente
interrumpe al procesador
‣ Al interrumpir, el control lo toma la rutina de interrupción de
tiempo.
‣ La frecuencia de interrupción es fijada por el kernel. Nunca por
el código usuario.
‣ Las Interrupciones pueden ser temporalmente diferidas
- Nunca por el código usuario!
- Aspecto crucial para implementar mecanismos de exclusión
mutua
Conmutación de modos:
Modo usuario a modo kernel
• Interrupciones
‣ Son gatilladas por el timer y dispositivos de E/S.

• Excepciones
‣ Son gatilladas por comportamientos no esperados de un
programa o también por sw malicioso.

• Llamadas al Sistema (también “Llamada a


Procedimiento Protegido”)
‣ Requerimiento de un programa al kernel, para realizar alguna
operación por su intermedio.
‣ Su número es limitado y están cuidadosamente escritas.
Conmutación de modos:
Modo kernel a modo usuario
• Al comienzo de un nuevo proceso o un nuevo thread
‣ Salto a la primera instrucción en un programa/thread.

• Retorno desde una interrupción, excepción o


llamada al sistema
‣ Reasumir una ejecución que estaba suspendida.

• Conmutación a otro proceso

• Notificación asincrónica al programa usuario.


Programas de usuario pueden recibir notificaciones
asincrónicas de eventos (Upcall)
El SO es SW que sólo responde
a interrupciones
Stacks

• ¿Para qué sirven?


‣ Cuando se llama a una función, es necesario guardar una
estructura de datos llamada “Stack Frame” que contiene la
dirección de retorno, sus argumentos y variables locales. Esta
estructura es accesible por el Stack Pointer.
‣ Entre otras cosas, el Stack permite llamadas recursivas a
funciones.
‣ Los Stack manejados por el SO son distintos a los Stacks de
usuarios (protección).
El Stacks de Interrupciones
• Este Stack se ubica en la región de memoria del
kernel.

• Puede ser un solo stack de interrupciones para


todos los procesos, pero los SO modernos asignan
un Stack de interrupciones por cada proceso a
nivel usuario. Entonces un proceso tiene ambos:
stack de kernel (interrupciones) y stack de usuario.

• ¿Por qué el manejador de interrupciones no puede


correr en el stack del proceso interrumpido?
¿Por qué el manejador de interrupciones no puede
correr en el stack del proceso interrumpido?

• Hay dos razones:

1. Confiabilidad: Si el SP (stack pointer) por un


bug apunta a una dirección errónea, el manejador
del kernel puede continuar trabajando en forma
apropiada.

2.Seguridad: En un multiprocesador, otros threads


corriendo en el mismo proceso pueden modificar
la memoria usuario durante la llamada al sistema y
puede modificar la dirección de retorno del kernel.
Ejemplo: Dos Stacks por proceso
Proceso 1 Proceso 2

Stack Stack

Código Código

Usuario Globales Globales

Heap Heap

Proceso 1 Proceso 2
Kernel
PCB 1 PCB 2
Stack Stack
Estados de un Proceso
Terminado
Creado
interrumpido
admitido exit

Ready Running
scheduler

Fin de I/O o wait I/O o wait


Wainting
Stacks e Interrupciones
Estados de Procesos
Running Ready to Run Waiting for I/O

Syscall
User Stack Proc2 Proc2 Proc2
Proc1 Proc1 Proc1
Main Main Main

I/O Driver
Top Half

Kernal Stack Syscall


Handler

User CPU User CPU


State State
Context Switch

• Cuando la CPU conmuta a otro proceso, el


sistema debe salvar el estado del antiguo
proceso y cargar el estado salvado del nuevo
proceso. Esta acción se denomina Context
Switch (Conmutación de contexto).

• El contexto de un proceso está representado en


su PCB.
Registro de Estado (PSW)
• La arquitectura x86 tiene un registro de hardware
llamado FLAGS que mantiene el estado del procesador.

• Bits de este registro son cambiados como resultado de


operaciones aritméticas.

• Bits de este registro indican la ocurrencia de


interrupciones. También las interrupciones se pueden
habilitar o enmascarar con un par de instrucciones
privilegiadas:
- CLI: deshabilita interrupciones
- STI: habilita interrupciones
Enmascaramiento de
Interrupciones

• El código que maneja interrupciones (interrupt


handler), corre con interrupciones desabilitadas.
‣ Cuando la interrupción se completa, se vuelve a habilitar.
‣ Deshabilitar, sólo significa diferir en tiempo.

• El kernel también puede desabilitar interrupciones


‣ Cuando elige el siguiente proceso/thread para correr.
‣ Si el tiempo es muy largo, se perderán eventos de E/S.
Manejadores de Interrupciones
(interrupt handler)
• El código que maneja una interrupción se
denomina interrupt handler (manejador de
interrupción).

• Un manejador de interrupciones no se puede


bloquear (no bloqueante). Corre hasta terminar
‣ Debe ser rápido para permitir capturar la siguiente interrupción.
‣ Toda espera debe ser acotada en tiempo

• Los drivers de dispositivos corren como threads de


kernel
Modo de transferencia
atómica (no interrumpible)
• Por ejemplo, la arquitectura x86 ante una
interrupción:
‣ Salva el SP actual
‣ Salva el Program Counter (PC)
‣ Salva el Process Status Word (PSW) actual (registro de códigos
de condición)
‣ Conmuta al stack del kernel: Push SP, PC y PSW en Stack
‣ Conmuta a modo kernel
‣ Direcciona el vector de interrupción
‣ El manejador de interrupción salva registros que puedan
corromperse
x86 antes de la interrupción
User-level Process Registers Kernel

foo () { handler() {
SS: ESP
while(...) { pusha
x = x+1; ...
CS: EIP
y = y-2; }
}
EFLAGS
}
Exception
User Stack Other Registers: Stack
EAX, EBX,

ESP: Stack pointer SS: Stack segment


EIP: Program counter CS: Code segment
x86 durante la interrupción
Justo en el momento que salta al handler
User-level Process Registers Kernel

foo () { handler() {
SS: ESP
while(...) { pusha
x = x+1; ...
CS: EIP
y = y-2; }
}
EFLAGS
}
Exception
User Stack other registers: Stack
EAX, EBX,

Error
EIP
CS
Indica evento EFLAGS
ESP
SS
x86 después de la
interrupción
El handler a comenzado la ejecución

User-level Process Registers Kernel

foo () { handler() {
SS: ESP
while(...) { pusha
x = x+1; ...
CS: EIP
y = y-2; }
}
EFLAGS
}
Exception
Stack other registers: Stack
EAX, EBX,

All
EBX Registers
EAX
EIP
CS
ESP
SS

Error
EIP
CS
EFLAGS
ESP
SS
Al final de la la interrupción
• El Handler restaura los registros que estaban
guardados en el stack.

• Atómicamente el proceso/thread que fue


interrumpido:
‣ Restaura el PC
‣ Restaura el SP
‣ Restaura el PSW
‣ Conmuta a modo usuario

Para el proceso, todo esto es transparente


Upcall: Interrupciones de SW
• Un Upcall es una interrupción por sw o también una
interrupción a nivel usuario. También “interrupciones
virtualizadas”
‣ Se denominan también señales (signals en UNIX y eventos asincrónicos
en Windows)
‣ Es un mecanismo que notifica a un proceso usuario de un evento que
necesita ser manejado en forma adecuada.

• Es un símil directo con las interrupciones del kernel


‣ Signal handler: puntos de entrada fijos
‣ Stack separado para el manejo de señales
‣ En forma automática se salvan/restauran registros y se reasume en forma
transparente.
‣ Enmascaramiento: se inhiben señales mientras se ejecuta el signal handler
Upcalls
App App

User User
Interrupción Upcall

Kernel Kernel
Kernel Kernel
Signals: Upcall
• Las señales permiten que una aplicación se
comporte de una forma similar a un kernel, es decir
responda a interrupciones.

• Los sistemas UNIX utilizan señales para notificar a


procesos que ha ocurrido un evento particular.

• Para manejar las señales recibidas se utiliza un


“signal handler”. La secuencia es:
‣ Una señal es generada por un evento particular
‣ Una señal es entregada a un proceso
‣ La señal es manejada por el proceso
… Signals

• La función estándar de UNIX para entregar una


señal a un proceso es:

kill(pid_t pid, int signal)

• kill especifica el pid del proceso al cual una señal


será despachada.
… Signals
• La llamada signal altera la acción por defecto.
Por ejemplo:
#include <signal.h> //contiene lista de posibles argumentos
signal(SIGINT, SIG_IGN) // cause the interrupt to be ignored

signal(SIGINT, Dir_func) //en este caso al llegar la señal se


//ejecuta la función cuya dirección
// es Dir_func
Ejemplo
#include<stdio.h>
#include<signal.h>
#include <unistd.h>

//manejador de SIGINT causado por Ctrl-C en


// teclado
Hola Mundo
Hola Mundo
void manejador_sigint(int sig) Hola Mundo
{ Senal capturada 2
printf("Senal capturada %d\n", sig); Hola Mundo
} Hola Mundo

int main()
{
signal(SIGINT, manejador_sigint);
while(1) {
printf("Hola Mundo\n");
sleep(1);
}
return 0;
}
Upcall: Antes
... signal_handler() {
x = y + z; ...
... }
Program Counter

Signal
Stack Pointer
Stack Stack
Upcall: Después
... signal_handler() {
x = y + z; ...
... }
Program Counter

Signal
Stack Pointer
Stack Stack

Saved
Registers

SP
PC
5 Llamadas al Sistema

• An la arquitectura ARM, la instrucción que permite


el acceso al kernel es SVC (Supervisor Call).
Cambia a modo kernel el privilegio del procesador

• SVC #numero: el número indica el handler del


kernel que se está solicitando.
Llamadas al sistema y
bibliotecas
Modo Usuario Modo Kernel

system_call:
sys_OPEN() {
... open() { ......
(syscall_table[SYS_OPEN])() .....
open()
... SYSCALL ........... }
} SYS_EXIT

código de
Invocación manejador de
“envoltorio (stub)” llamada al
a la llamada llamada al
de la llamada al sistema sistema
al sistema sistema
Generalización
User Program Kernel

main () { syscall(arg1, arg2) {


syscall(arg1, arg2); // do operation
} }

(1) (6) (3) (4)

User Stub (2) Kernel Stub


Hardware Trap
syscall (arg1, arg2) { handler() {
trap // copy arguments
return // from user memory
Trap Return
} //check arguments
(5) syscall(arg1, arg2);
// copy return value
// into user memory
return;
}
• El Manejador de llamadas al sistema del Kernel
(handler):

๏ Localiza los argumentos


- En registros o en stack usuario

๏ Copia los argumentos


- De la memoria usuario a memoria kernel
- Pone cuidado con operaciones maliciosas

๏ Valida argumentos
- Protege al kernel de errores en código usuario

๏ Copia los resultados en memoria usuario


Ejemplo: Web Server
Muchas llamadas al sistema

Server
request 4. parse request reply
9. format reply
buffer buffer

1. network 10. network 5. file


socket 3. kernel socket read 8. kernel
read copy write copy

Kernel

11. kernel copy


from user buffer
into network buffer

12. format outgoing 6. disk


2. copy arriving 7. disk
packet and DMA request
packet (DMA) data (DMA)

Hardware

Network Interface Disk Interface


6 Booteo del SO
Physical
Memory
(1)
BIOS copies BIOS
Disk bootloader
Bootloader
instructions
(2) and data
Bootloader Bootloader
copies OS kernel
OS kernel
OS kernel
Login app instructions
and data
(3)
OS kernel copies
login application
Login app
instructions
and data
7 Máquinas Virtuales
• Algunos kernels de SO proporcionan la abstracción
de una completa máquina virtual a nivel de usuario.

• ¿Cómo se puede lograr esto?. Por ejemplo


interrupciones, excepciones y llamadas al sistema
en este contexto.

• Definiciones: El SO que proporciona la abstracción


de máquina virtual se denomina SO host. El SO
que corre dentro de la máquina virtual se denomina
SO guest (huesped).
Estructura
Guest User Mode Guest Guest
Hoste User Mode Process Process Guest
... Program
Syscall Counter
...
Host User Mode
Guest Kernel Mode
Guest Kernel Timer
Guest PC Guest Guest Handler
Guest SP Exception Guest file system Interrupt
Guest Flags Stack and other kernel Table Syscall
services Handler

Host KernelMode
Host Kernel Timer
Host PC Host Host Handler
Host SP Exception Virtual Interrupt
Host Flags Stack Disk Table Syscall
Handler

Hardware Physical
Disk
Activación del Kernel
Huésped
• El SO host proporciona la ilusión que el kernel guest está
corriendo en un HW real.

• Para simular el disco del guest, el SO host utiliza el sistema de


archivos. De la misma forma la memoria, interfaces de red, etc…
se simulan con memoria virtual e interfaces de red virtuales.

• En el proceso de booteo, el host inicializa sus vectores de


interrupción apuntando a los handler en su memoria.

• Al activar la máquina virtual el host carga el bootloader del guest


desde el disco virtual. Este carga el kernel guest desde el disco
virtual y comienza su ejecución inicializando sus tablas de
interrupción.
…Activación del Kernel
Huésped
• Proceso de activación del kernel huésped:

1. El host carga el bootloader del huésped desde


el disco virtual y comienza a correr.

2. El bootloader huésped carga el kernel huésped


desde el disco virtual y comienza a correr.

3.El kernel huésped inicializa su vector de


interrupciones para apuntar a sus propios
“handlers”.
…Activación del Kernel
Huésped
4. El kernel huésped carga un proceso desde el
disco virtual a la memoria del huésped.

5. Para iniciar el proceso, el kernel huésped


ejecuta una instrucción para reasumir ejecución
nivel usuario (reti return from interrupt en x86).
Esta instruccion es privilegiada y es capturada
por el kernel host porque se trata de un cambio
de priviliegio.
…Activación del Kernel
Huésped

6. El kernel host simula la transferencia de modo


como si fuera directamente ejecutada sobre él:
restaura PC, SP, PSW
Ejecución de Llamada al
Sistema por el Huésped
• Para el HW solo existe el kernel host y por lo tanto
los trap del huésped llegan al handler del host.
Pero esta llamada no era para el host. Entonces:

a) El kernel host salva PC, PSW y Stack usuario en el


Stack de interrupciones del huésped.

b) El kernel host transfiere control al kernel huésped,


al comienzo del handler pero con el kernel
huésped corriendo en modo usuario.
…Ejecución de Llamada al
Sistema por el Huésped
c) El kernel huésped ejecuta la llamada al sistema
salvando el estado de usuario y verificando
argumentos.

d) Cuando el kernel huésped intenta retornar de la


llamada al sistema a modo usuario, genera una
excepción bajando al kernel host.

e) El kernel host restaura el estado del proceso


usuario volviendo a modo usuario tal como si el SO
huésped hubiera retornado directamente.
Sistemas Operativos
Capítulo 2 El Kernel
Prof. Javier Cañas R.

Вам также может понравиться