Final Flashcards

1
Q

¿Qué es una system call? ¿Para qué se usan? ¿Cómo funcionan? Explicar en detalle el funcionamiento de una system call en particular.

A

Syscall es un tipo de instrucción, son llamadas al sistema.Sirven para proveer funcionalidad, que solo puede ser accedida por el kernel, a las aplicaciones de usuario.A diferencia de una llamada a subrutina común y corriente, las llamadas al sistema requieren cambiar el nivel de privilegio, un cambio de contexto, a veces una interrupción, etc. Los pasos son los mismos que para las interrupciones:

  1. El hardware mete el PC, PSW, registros, etc. a la pila.
  2. El hardware carga el nuevo PC del vector de interrupciones.
  3. Procedimiento en lenguaje ensamblador guarda los registros.
  4. Procedimiento en lenguaje ensamblador establece la nueva pila.
  5. El servicio de interrupciones de C se ejecuta.
  6. El scheduler decide que proceso se va a ejecutar a continuación.
  7. Procedimiento en C regresa al código en ensamblador.
  8. Procedimiento en lenguaje ensamblador inicia el nuevo proceso actual.

Las llamadas más típicas de un sistema son: *Open *Read *Write *Close *Wait *Exec *Fork *Exit *Kill
Llamada al sistema fork()
En un sistema operativo, hace referencia a la creación de una copia de sí mismo por parte de un programa, que entonces actúa como un “proceso hijo” del proceso originario, ahora llamado “padre”. Los procesos resultantes son idénticos, salvo que tienen distinto número de procesos.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

¿Las system calls son universales a todos los sistemas operativos o son dependientes de cada sistema?

A

No son universales, cada sistema operativo provee la interfaz para interactuar con su núcleo.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

¿Para qué sirve la system call fork? ¿Qué debilidades tiene? Comparar con vfork y la creación de threads.

A

La system call fork se utiliza en sistemas operativos Unix y Linux para crear un nuevo proceso, llamado proceso hijo, que es una copia del proceso padre. El proceso hijo recibe una copia del espacio de memoria del proceso padre, incluidas las variables, el estado del programa y los descriptores de archivos.

Funcionamiento de fork
Creación del Proceso Hijo:

fork crea un nuevo proceso duplicando el proceso que lo llama.
Ambos procesos, el padre y el hijo, continúan ejecutándose desde el punto donde se realizó la llamada a fork.
Espacio de Memoria:

El proceso hijo tiene una copia exacta del espacio de memoria del proceso padre en el momento de la llamada a fork.
Aunque inicialmente comparten el mismo espacio de memoria, los cambios realizados por uno no afectan al otro debido a la técnica de “Copy on Write” (COW).
Retorno de Valores:

fork retorna dos veces: una vez en el proceso padre y otra en el proceso hijo.
En el proceso padre, fork retorna el PID del hijo.
En el proceso hijo, fork retorna 0.
Debilidades de fork
Uso de Recursos:

fork puede consumir muchos recursos del sistema, especialmente memoria, ya que inicialmente crea una copia completa del espacio de memoria del proceso padre.
Eficiencia:

Aunque la técnica de Copy on Write ayuda a mitigar el uso intensivo de memoria, la duplicación inicial del espacio de memoria puede ser costosa en términos de tiempo y recursos.
Complejidad:

Manejar la sincronización y comunicación entre el proceso padre e hijo puede ser complejo y propenso a errores.
Comparación con vfork y la Creación de Threads
vfork
Propósito:
vfork es una variante de fork diseñada para casos donde el proceso hijo ejecuta una llamada a exec inmediatamente después de ser creado.
Funcionamiento:
vfork no duplica el espacio de memoria del proceso padre. En cambio, el proceso hijo comparte el mismo espacio de memoria que el padre hasta que se llama a exec o exit.
El proceso padre se bloquea hasta que el proceso hijo llame a exec o exit.
Ventajas:
Más eficiente en términos de memoria y tiempo en comparación con fork, ya que no se realiza una copia completa del espacio de memoria.
Desventajas:
Compartir el mismo espacio de memoria entre padre e hijo puede ser riesgoso y puede llevar a comportamientos no deseados si el proceso hijo modifica el espacio de memoria antes de llamar a exec o exit.
Creación de Threads
Propósito:
Los threads (hilos) son una forma de concurrencia dentro del mismo proceso, compartiendo el mismo espacio de memoria.
Funcionamiento:
Los threads se crean dentro de un proceso y comparten el mismo espacio de direcciones, variables globales y descriptores de archivos.
Ventajas:
Más ligeros y rápidos de crear y destruir en comparación con procesos.
Menor consumo de memoria y recursos del sistema, ya que no requieren duplicar el espacio de memoria.
Facilita la comunicación y el intercambio de datos entre hilos debido a que comparten el mismo espacio de memoria.
Desventajas:
Mayor riesgo de problemas de concurrencia como condiciones de carrera y problemas de sincronización.
Un fallo en un thread puede afectar a todo el proceso, ya que todos los threads comparten el mismo espacio de memoria.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Diferencias entre system calls para crear procesos entre Linux y Windows.

A

Linux y Windows tienen arquitecturas de núcleo diferentes, lo que afecta cómo se gestionan los procesos. En Linux, el núcleo sigue una arquitectura monolítica, donde todo el sistema operativo está contenido en el núcleo. Esto significa que el núcleo maneja la gestión de procesos, la gestión de memoria, los controladores de dispositivos y las llamadas al sistema dentro del espacio del núcleo. Por otro lado, Windows utiliza una arquitectura de núcleo híbrido, que combina elementos de arquitecturas monolíticas y microkernel. El núcleo de Windows proporciona servicios esenciales y gestiona recursos básicos del sistema, mientras que los controladores de dispositivos y algunos servicios del sistema se ejecutan en modo usuario. En cuanto a la gestión de procesos, tanto Linux como Windows utilizan conceptos similares como la planificación de procesos, la gestión de memoria y la comunicación entre procesos, pero los detalles de implementación difieren debido a sus arquitecturas de núcleo. En general, las diferencias en la arquitectura del núcleo entre Linux y Windows resultan en enfoques variados para la gestión de procesos y el manejo de recursos del sistema.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

¿Cómo funcionan los estados de un proceso? Ready, bloqueado, running. Explicar las transiciones de cada estado a cada estado (en particular, de waiting a ready).

A

En un sistema operativo, un proceso puede encontrarse en diferentes estados durante su ciclo de vida. Los estados principales son:

Listo (Ready): El proceso está preparado para ejecutarse pero no puede hacerlo porque la CPU está ocupada con otros procesos.
Corriendo (Running): El proceso está actualmente en ejecución, utilizando la CPU.
Bloqueado (Blocked/Waiting): El proceso no puede continuar su ejecución hasta que ocurra un evento externo, como la finalización de una operación de entrada/salida (E/S).
Terminado (Terminated): El proceso ha completado su ejecución.
Transiciones entre estados
De Listo a Corriendo: Cuando la CPU se libera y el planificador de procesos selecciona un proceso de la cola de listos para su ejecución.
De Corriendo a Bloqueado: Cuando un proceso en ejecución necesita esperar por algún evento externo (como una operación de E/S), pasa al estado bloqueado.
De Bloqueado a Listo: Una vez que el evento externo que el proceso estaba esperando ocurre (por ejemplo, una operación de E/S se completa), el proceso pasa de bloqueado a listo.
De Corriendo a Listo: Si el proceso en ejecución es interrumpido por el planificador de procesos (por ejemplo, debido a la política de tiempo compartido), pasa al estado listo, esperando su turno para ejecutarse nuevamente.
De Corriendo a Terminado: Cuando el proceso completa su ejecución.
De Listo a Terminado: Esta transición generalmente no ocurre directamente en la práctica, ya que un proceso debe estar en ejecución (Corriendo) para completar su ejecución y pasar a Terminado.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

¿Qué estructura se debe mantener en memoria para poder tener procesos? Hablar de la tabla de procesos.

A

El sistema operativo mantiene una tabla (un arreglo de estructuras), llamada tabla de procesos, con una entrada por cada proceso. Esta entrada contiene información importante sobre el estado del proceso, incluyendo su contador de programa, puntero de pila, asignación de memoria, el estado de sus archivos abiertos, su información de contabilidad y planificación, y todo lo demás sobre el proceso que debe guardarse cuando el proceso se cambia de estado de ejecución a estado de listo o bloqueado, para que pueda reiniciarse más tarde como si nunca hubiera sido detenido.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

¿Qué es un proceso, un thread y en qué se diferencian?

A

Un proceso es una unidad independiente de ejecución que contiene su propio espacio de memoria. Es un programa en ejecución que tiene recursos asignados, como memoria y tiempo de CPU, permitiéndole operar de forma independiente. Los procesos se comunican a través de mecanismos de comunicación interprocesos (IPC) y están aislados entre sí, lo que significa que el fallo en un proceso no afecta directamente a otros.

Un thread o hilo es una unidad de ejecución más ligera dentro de un proceso. A diferencia de los procesos, los threads de un mismo proceso comparten el mismo espacio de memoria y recursos, como archivos y variables de datos. Esto permite una comunicación más directa y eficiente a través de la memoria compartida, pero también implica que un fallo en un thread puede afectar a todos los threads del mismo proceso.

Diferencias principales entre un proceso y un thread
Espacio de memoria: Los procesos tienen su propio espacio de memoria separado, mientras que los threads comparten el espacio de memoria dentro del mismo proceso.
Sobrecarga: Los procesos tienen una sobrecarga mayor debido a la gestión de memoria y recursos separados, mientras que los threads son más eficientes en el uso de recursos debido a la compartición de memoria y recursos.
Ejecución: Los procesos operan de manera independiente, mientras que la ejecución de los threads depende del proceso al que pertenecen y pueden correr en paralelo dentro de este.
Control: Los procesos pueden ser iniciados, detenidos y controlados de manera independiente, mientras que los threads son controlados dentro del contexto de un proceso.
Aislamiento: Los procesos están aislados entre sí, lo que proporciona seguridad y estabilidad al sistema, en contraste con los threads que están expuestos a fallos relacionados entre sí debido a la compartición de recursos.
Impacto de fallos: Un fallo en un proceso no afecta a otros procesos, mientras que un fallo en un thread puede impactar a todos los threads del mismo proceso.
Tiempo de creación: La creación de procesos toma más tiempo debido a la necesidad de asignar recursos exclusivos, en comparación con los threads que se pueden crear más rápidamente.
Casos de uso
Procesos: Son adecuados para aplicaciones que requieren aislamiento y seguridad en la ejecución, como aplicaciones que manejan datos sensibles o críticos.
Threads: Ideales para tareas que requieren una comunicación frecuente y acceso a recursos compartidos, como las aplicaciones que realizan muchas tareas de fondo que son menos intensivas en CPU pero que necesitan interactuar entre sí de manera eficiente.
En resumen, elegir entre procesos y threads depende de los requerimientos específicos de la aplicación en términos de aislamiento, seguridad, rendimiento y eficiencia en la comunicación.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

¿Qué debería agregar a la PCB para manejar los threads?

A

Deberíamos agregar una lista de threads con los valores de los registros y el estado del stack para poder retomar la ejecución de estos.
En la PCB del proceso que tiene varios threads incluye una tabla con los threads id

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

¿Qué pasaría si los threads compartieran el stack?

A

Si los threads compartieran stack, se molestan mutuamente a la hora de ejecutarse porque uno podría cambiar el valor de una variable o cambiar el contexto y cuando pase a ejecutarse el otro thread el contexto sería erróneo o el valor de la variable no sería el esperado.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Qué tendría que ver en un sistema para que piense que va a andar mejor agregando:
más procesadores.
más memoria.

A

Más procesador se necesita cuando la carga del sistema es alta, es decir hay procesos listos que no se están ejecutando.
Más memoria se necesita cuando tenemos muchos procesos que necesitan memoria y esta no alcanza.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Hablar de strace y ptrace.

A

Ambas son syscalls.
El programa strace, que está disponible en los sistemas Linux, lista cada llamada al sistema a medida que se ejecuta. strace—rastrea las llamadas al sistema invocadas por un proceso.

ptrace permite que un proceso controle a otro, permitiendo al controlador inspeccionar y manipular el estado interno de su objetivo. ptrace es utilizado por depuradores y otras herramientas de análisis de código, principalmente como ayudas para el desarrollo de software.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Describir los objetivos que pueden tener las políticas de scheduling (fairness, carga del sistema, etc.).

A

Ecuanimidad (fairness): que cada proceso reciba una dosis “justa” de CPU (para alguna definición de justicia).
Eficiencia: tratar de que la CPU este ocupada todo el tiempo.
Carga del sistema: minimizar la cant. de procesos listos que están esperando CPU.
Tiempo de respuesta: minimizar el tiempo de respuesta percibido por los usuarios interactivos.
Latencia: minimizar el tiempo requerido para que un proceso empiece a dar resultados.
Tiempo de ejecución: minimizar el tiempo total que le toma a un proceso ejecutar completamente.
Rendimiento (throughput): maximizar el número de procesos terminados por unidad de tiempo.
Liberación de recursos: hacer que terminen cuanto antes los procesos que tiene reservados más recursos.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

¿Qué objetivo prioriza SJF y por qué no se usa en la práctica?

A

Prioriza el trabajo más corto primero. Está ideada para sistemas donde predominan los trabajos batch. Está orientada a maximizar el throughput.En esos casos, muchas veces se puede predecir la duración del trabajo o al menos clasificarlo.Si conozco las duraciones de antemano, es óptimo.
Otra alternativa es no pensar en la duración total, sino más bien en cuanto tiempo necesita hasta hacer E/S de nuevo.
No se usa porque el problema real es como saber cuanta CPU va a necesitar un proceso.Una alternativa es usar la info del pasado para predecir. Puede salir mal si los procesos tienen comportamiento irregular.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

¿Cómo funciona el scheduling con múltiples colas?

A

Colas con 1, 2, 4, 8 quanta c/u. A la hora de elegir un proceso la prioridad la tiene siempre la cola con menos quanta.
Cuando a un proceso no le alcanza su cuota de CPU es pasado a la cola siguiente, lo que disminuye su prioridad, pero le asigna más tiempo de CPU en el próximo turno.
Los procesos de máxima prioridad, los interactivos en gral, van a la cola de máxima prioridad. Se puede hacer que cuando un proceso termina de hacer E/S vuelva a la cola de máxima prioridad, porque se supone que va a volver a hacerse interactivo.
La idea general es minimizar el tiempo de respuesta para los procesos interactivos, suponiendo que los computos largos son menos sensibles a demoras.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

¿Hay algún problema con que las prioridades fueran fijas?

A

Un problema importante con los algoritmos de planificación por prioridad es el bloqueo indefinido, o inanición. Un proceso que está listo para ejecutarse pero esperando por la CPU puede considerarse bloqueado. Un algoritmo de planificación por prioridad puede dejar algunos procesos de baja prioridad esperando indefinidamente. En un sistema informático muy cargado, un flujo constante de procesos de mayor prioridad puede evitar que un proceso de baja prioridad obtenga la CPU. Generalmente, sucederá una de dos cosas. O el proceso eventualmente se ejecutará (a las 2 A.M. del domingo, cuando el sistema finalmente esté ligeramente cargado), o el sistema informático eventualmente fallará y perderá todos los procesos de baja prioridad no terminados. Una solución al problema del bloqueo indefinido de los procesos de baja prioridad es el envejecimiento. El envejecimiento implica aumentar gradualmente la prioridad de los procesos que esperan en el sistema durante mucho tiempo.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Hablar sobre la afinidad de un procesador. ¿Qué información extra tenemos que tener en la PCB para mantener afinidad en un sistema multicore?

A

Uno de los problemas que enfrentan los algoritmos de scheduling al haber varios procesadores, es que cada uno de los procesadores tiene su memoria caché, y si uno de los procesos es ejecutado en un cpu para luego ser ejecutado en otro, no hay cache hits y se hace más lento (siempre teniendo en cuenta scheduling con desalojo). Una mitigación para esto es utilizar el concepto de afinidad al procesador, es decir, tratar de que un proceso siempre utilice el mismo procesador, aunque se tarde un poco más de tiempo en obtenerlo. Dentro de afinidad al procesador, esta puede ser afinidad dura, es decir que un proceso siempre se va a ejecutar en el mismo procesador, o afinidad blanda, donde un proceso trata de ejecutarse en el mismo procesador pero podría llegar a cambiar y ejecutarse en otro.
Otro desafío a tener en cuenta es el balance de carga entre los procesadores, para esto se usa push y pull migration. En push migration, una tarea se encarga de revisar las cargas de cada uno de los procesadores y mueve procesos de una cola a otro para balancearlos. Pull migration es cuando un procesador en estado idle le saca un proceso de la cola a otro procesador para ejecutarlo.

En el PCB deberíamos tener en qué procesador se estuvo ejecutando el proceso.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
17
Q

Explicar el problema de inversión de prioridades.

A

Un desafío de planificación surge cuando un proceso de mayor prioridad necesita leer o modificar datos del núcleo que actualmente están siendo accedidos por un proceso de menor prioridad, o una cadena de procesos de menor prioridad. Dado que los datos del núcleo generalmente están protegidos con un bloqueo, el proceso de mayor prioridad tendrá que esperar a que el de menor prioridad termine con el recurso. La situación se complica si el proceso de menor prioridad es preemptado a favor de otro proceso con una prioridad más alta.

Como ejemplo, supongamos que tenemos tres procesos—L, M y H—cuyas prioridades siguen el orden L < M < H. Supongamos que el proceso H requiere un semáforo S, que actualmente está siendo accedido por el proceso L. Normalmente, el proceso H esperaría a que L termine de usar el recurso S. Sin embargo, ahora supongamos que el proceso M se vuelve ejecutable, preemptando así al proceso L. Indirectamente, un proceso con una prioridad más baja—el proceso M—ha afectado el tiempo que el proceso H debe esperar para que L libere el recurso S.

Este problema de vivacidad se conoce como inversión de prioridad, y solo puede ocurrir en sistemas con más de dos prioridades. Típicamente, la inversión de prioridad se evita implementando un protocolo de herencia de prioridad. Según este protocolo, todos los procesos que están accediendo a recursos necesarios para un proceso de mayor prioridad heredan la prioridad más alta hasta que terminan con los recursos en cuestión. Cuando terminan, sus prioridades vuelven a sus valores originales.

En el ejemplo anterior, un protocolo de herencia de prioridad permitiría que el proceso L herede temporalmente la prioridad del proceso H, evitando así que el proceso M preempte su ejecución. Cuando el proceso L haya terminado de usar el recurso S, renunciaría a su prioridad heredada de H y asumiría su prioridad original. Debido a que el recurso S ahora estaría disponible, el proceso H—no M—se ejecutaría a continuación.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
18
Q

¿Para qué necesitamos sincronización entre procesos? ¿Qué soluciones nos ofrece el HW? Explicar el caso para monoprocesador y para multiprocesador. (instrucciones atómicas y deshabilitar interrupciones)

A

Se generan condiciones de carrera. Toda ejecución debería dar un resultado equivalente a alguna ejecución secuencial de los mismos procesos.

HW:

Barrera de memoria: cuando se ejecuta esta instrucción, el sistema asegura que todas las operaciones de carga y almacenamiento se completen antes de que cualquier operación de carga o almacenamiento posterior sea ejecutada. Por lo tanto, incluso si las instrucciones fueron reordenadas, la barrera de memoria asegura que las operaciones de almacenamiento se completen en memoria y sean visibles para otros procesadores antes de que se realicen futuras operaciones de carga o almacenamiento.
Una alternativa podría ser la de suspender todo tipo de interrupciones dentro de la sección crítica. Esto elimina temporalmente la multiprogramación. Aunque garantiza la correcta actualización de los datos compartidos, trae todo tipo de problemas.

TestAndSet: La idea es que pone 1 y devuelve el valor anterior, pero de manera atómica. Asumo que se posee un registro atómico SWMR (Single-Writer/Multiple-Reader).

Explique ventajas y desventajas de cada una. No hay mejor o peor, simplemente tienen usos distintos. Ejemplos:

TAS sirve para hacer TASLock y TTASLock.
CAS tiene número de consenso infinito, a diferencia de TAS que sólo es 2.
Variables atómicas: proporcionan operaciones atómicas en tipos de datos básicos como enteros y booleanos.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
19
Q

¿Cómo nos afecta si el scheduler es preemptive o non-preemptive en la implementación de un semáforo?

A

Si el scheduler es preemptive, al momento de despertar el proceso bloqueado, se revisa si su prioridad es mayor al que actualmente está ejecutando. Si lo es, se lo desaloja y se le asigna la CPU al proceso recién despertado— en el contexto de Linux, esto se conoce como wake-up preemption.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
20
Q

Evaluar si están bien o mal utilizadas en los siguientes ejemplos las primitivas de sincronización:
Usar TASLock (spinlock) para acceder a disco.
Usar semáforos para incrementar un contador.
Usar un contador atómico para un recurso que tienen que poder acceder 3 procesos a la vez.
usar spinlock para un recurso que tienen que poder acceder 3 procesos a la vez.
Acceso exclusivo a disco utilizando TAS Lock.

A

No es ideal. TAS Lock hace busy waiting, lo cual implica que el proceso se mantiene ciclando hasta que logra obtener el lock. Hacer esto significa un desperdicio de tiempo de CPU dado que mientras cicla el procesador no hace ningún trabajo real. Debido a esto, no es conveniente usar un TAS Lock cuando el lock se mantiene por largos períodos de tiempo, como en el caso de hace E/S a disco. El disco es un dispositivo muy lento en términos del CPU, por lo cual los procesos que se encuentren haciendo busy waiting a la espera de que se libere el TAS Lock desperdiciarán mucho tiempo de procesamiento.

En este caso es mejor usar un mutex implementado mediante un semáforo, ya que el SO bloqueará a los procesos que fallen en obtener el acceso a este y los desbloqueará a medida que se vaya liberando. Esto permite que el SO ponga a ejecutar otras tareas mientras el proceso que tiene el lock realiza el acceso a disco. Los procesos esperando por el lock no hacen busy waiting sino que permanecen bloqueados hasta que se libera el lock, momento en el cual el SO despierta a alguno de ellos.
Acceso a un contador que se desea incrementar mediante un semáforo binario.

No es correcta. Las operaciones de los semáforos se implementan mediante system calls, lo cual implica que se debe realizar un cambio de contexto cada vez que son realizadas. Esto tiene un overhead que no se justifica para un acceso exclusivo de tan corto tiempo como lo es incrementar un contador.

Para esta situación es mejor usar una variable numérica atómica que puede ser incrementada con una única instrucción atómica del procesador. Esto es muy eficiente, pero requiere soporte del hardware. A falta del mismo, la alternativa es usar un TAS Lock ya que no requiere cambiar el contexto y el hecho de que el lock se mantenga por un tiempo corto implica que no se perderán tantos ciclos haciendo busy waiting.

Acceso a una estructura que permite hasta 3 accesos simultáneos con semáforos.

Es correcta. Los semáforos tienen un valor que puede ser decrementado e incrementado con las operaciones wait y signal. Si el valor del semáforo es menor o igual a 0, un proceso que hace wait se bloquea y queda en espera. Cuando otro proceso hace signal, el SO incrementa el valor del semáforo y despierta a uno de los procesos en espera. Este último continúa su ejecución decrementando el valor del semáforo antes de hacerlo.

Con esto, se puede proteger el acceso a la estructura con el uso de un semáforo cuyo valor inicial es 3. Los procesos hacen wait antes de acceder a ella y hacen signal una vez que terminaron. De esta forma, sólo 3 procesos podrán obtener el acceso mientras el resto queda en espera. A medida que estos van haciendo signal, se van despertando los procesos en espera uno por uno.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
21
Q

Diferencia entre spin lock y semáforos (hablar de TTAS). ¿En qué contexto preferimos uno sobre el otro y por qué?.

A

Spinlock hace busy waiting mientras que los semáforos no.Las operaciones de los semáforos se implementan mediante system calls, lo cual implica que se debe realizar un cambio de contexto cada vez que son realizadas.
Entonces preferimos spinlock para situaciones donde se cambie constantemente de proceso, para no tener tanto busy waiting, mientras que el semáforo es preferible para situaciones donde los procesos se ejecuten por más tiempo justificando así el cambio de contexto.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
22
Q

¿Cómo implementamos una sección crítica con spin locks?

A

Un spinlock es un mecanismo de sincronización utilizado para controlar el acceso a una sección crítica en programación concurrente. En lugar de poner en espera a los hilos que no pueden acceder a la sección crítica, un spinlock hace que estos hilos entren en un bucle de espera activo hasta que el recurso esté disponible.

  1. Inicialización: El spinlock se inicia en un estado desbloqueado, indicando que el recurso está disponible.
  2. Adquisición: Un hilo intenta adquirir el spinlock mediante una operación atómica que establece el estado del bloqueo a ocupado. Si el bloqueo ya está ocupado, el hilo entra en un bucle de espera activa.
  3. Liberación: Una vez que el hilo termina de usar la sección crítica, libera el spinlock, volviendo a ponerlo en un estado desbloqueado.
  • Consumo de CPU: Los spinlocks pueden consumir mucha CPU debido a la espera activa, por lo que son más adecuados para secciones críticas de corta duración.
  • Evitar Deadlocks: Es crucial diseñar el uso de spinlocks para evitar deadlocks, donde varios hilos podrían quedarse esperando indefinidamente.

En resumen, los spinlocks son útiles para sincronizar el acceso a recursos en situaciones donde el tiempo de espera es breve, gracias a su implementación basada en operaciones atómicas para asegurar que solo un hilo acceda a la vez a la sección crítica.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
23
Q

Explicar el problema clásico de lectores y escritores. Explicar cómo podemos evitar inanición del escritor.

A

Hay una variable compartida.Los escritores necesitan acceso exclusivo.Pero los lectores pueden leer simultáneamente.Propiedad SWMR (Single-Writer/Multiple-Readers):
Puede haber inanición de escritores.¿Por qué? Puede ser que haya siempre (al menos) un lector.Se viola la propiedad de progreso global dependiente(STARVATION-FREEDOM).Esto es, si todo proceso sale de CRIT entonces todo proceso que está en TRY entra inevitablemente a CRIT .
Supongamos que tenemos una base de datos compartida entre varios procesos concurrentes, a la que
podemos acceder usando las funciones dadas write y read. Algunos de estos procesos podrían querer
solo leer la base de datos, mientras que otros podrían querer actualizarla. Distinguimos entre estos dos
tipos de procesos a partir de referirnos a los primeros como lectores y a los últimos como escritores.
Queremos que los lectores puedan leer en simultáneo con otros lectores, pero que los escritores necesiten
acceso exclusivo sobre la base para poder escribir. Esta propiedad se conoce como Single-Writer/Multiple
Readers (SWMR). Concretamente, queremos que se cumplan las siguientes condiciones:
* Cualquier número de lectores puede estar en la sección crítica de manera simultánea.
* Los escritores deben tener acceso exclusivo a la sección crítica.
En otras palabras, un escritor no puede entrar a la sección crítica mientras que cualquier otro proceso
(escritor o lector) esté allí. Mientras haya algún escritor en la sección critica, no puede entrar ningún
otro proceso. En primera instancia, buscamos una solución que nos garantice el cumplimiento de estas
restricciones, que permita el acceso a la base de datos a escritores y lectores, y que sea libre de deadlocks.
Vamos a necesitar las siguientes variables compartidas para resolver el problema.
1 int readers = 0
2 semaphore mutex = Semaphore(1)
3 semaphore roomEmpty = Semaphore(1)
El contador readers mantiene un registro de cuántos lectores hay actualmente en la sección crítica—mutex protege el contador compartido. roomEmpty vale 1 si no hay ningún proceso (lector o escritor) en la sección crítica, y 0 en el caso contrario. El código para escritores es simple. Si la sección crítica está vacía, un escritor puede entrar, pero entrar tiene el efecto de excluir a todos los demás procesos.
1 roomEmpty.wait()
2 write()
3 roomEmpty.signal()
Notemos que cuando el escritor sale de la sección crítica, ésta queda vacía. Esto se debe a que ningún otro proceso pudo haber entrado mientras el escritor estaba en la sección crítica.
Para el caso de los lectores, necesitamos mantener un registro de la cantidad de lectores que actualmente están en la sección crítica. De este modo, vamos a poder distinguir el caso en el que entra el primer lector y el caso en el que sale el último lector.
El primer lector que llega tiene que esperar por roomEmpty.
* Si la sección crítica está vacía, entonces el lector procede y, al mismo tiempo, restringe la entrada de nuevos escritores. Los lectores subsiguiente pueden entrar, porque ninguno de ellos intenta esperar por roomEmpty.
* Si ya había un escritor en la sección crítica, entonces el primer lector espera por roomEmpty. Como el lector mantiene el mutex, cualquier lector subsiguiente se quedará esperando por el mutex.
El código luego de la sección crítica es similar. El último lector en salir de la sección crítica apaga las luces—esto es, hace un signal en roomEmpty, permitiendo que si había algún escritor esperando, éste pueda entrar.
1 mutex.wait()
2 readers += 1
3 if readers == 1: # el primer lector bloquea CRIT
4 roomEmpty.wait() # para uso exclusivo de lectores
5 mutex.signal()
6
7 read()
8
9 mutex.wait()
10 readers -= 1
11 if readers == 0:
12 roomEmpty.signal() # el último lector desbloquea CRIT
13 mutex.signal()

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
24
Q

Se nos muestra un árbol de procesos donde cada proceso tiene una serie de page frames asignados. Explicar las siguientes situaciones:
¿Por qué todos los procesos de un sistema compartirían una página? (páginas del kernel o bibliotecas compartidas)
¿Por qué dos procesos específicos podrían compartir una página? (hablar de fork y copy-on-write)

A

La estrategia más común consiste en hacer copy-on-write: Al crear un nuevo proceso se utilizan las mismas páginas.Hasta que alguno de los dos escribe en una de ellas. Ahí se duplican y cada uno queda con su copia independiente.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
25
Q

¿Para qué sirve la paginación de la memoria? ¿Qué ventajas tiene sobre utilizar direcciones físicas? Hablar sobre el tamaño de las páginas y cómo se relaciona con el tamaño de los bloques en disco. (hablar de fragmentación interna y fragmentación externa)

A

La paginación evita la fragmentación externa y la necesidad asociada de compactación, dos problemas que afectan la asignación de memoria contigua. Debido a que ofrece numerosas ventajas, la paginación en sus diversas formas se utiliza en la mayoría de los sistemas operativos, desde aquellos para grandes servidores hasta los para dispositivos móviles. La paginación se implementa mediante la cooperación entre el sistema operativo y el hardware de la computadora.

El método básico para implementar la paginación implica dividir la memoria física en bloques de tamaño fijo llamados marcos y dividir la memoria lógica en bloques del mismo tamaño llamados páginas. Cuando se va a ejecutar un proceso, sus páginas se cargan en cualquier marco de memoria disponible desde su fuente (un sistema de archivos o el almacén de respaldo). El almacén de respaldo se divide en bloques de tamaño fijo que son del mismo tamaño que los marcos de memoria o en grupos de múltiples marcos.

Cada dirección generada por la CPU se divide en dos partes: un número de página (p) y un desplazamiento de página (d):

El número de página se utiliza como un índice en la tabla de páginas por proceso. A continuación, se describen los pasos que sigue la MMU para traducir una dirección lógica generada por la CPU a una dirección física:

Extraer el número de página p y usarlo como un índice en la tabla de páginas.
Extraer el número de marco correspondiente f de la tabla de páginas.
Reemplazar el número de página p en la dirección lógica con el número de marco f.
Cuando utilizamos un esquema de paginación, no tenemos fragmentación externa: cualquier marco libre puede ser asignado a un proceso que lo necesite. Sin embargo, podemos tener algo de fragmentación interna. Nótese que los marcos se asignan como unidades. Si los requisitos de memoria de un proceso no coinciden con los límites de la página, es posible que el último marco asignado no esté completamente lleno.

Si el tamaño del proceso es independiente del tamaño de la página, esperamos que la fragmentación interna promedio sea de media página por proceso. Esta consideración sugiere que los tamaños de página pequeños son deseables. Sin embargo, cada entrada de la tabla de páginas conlleva un costo adicional, y este costo se reduce a medida que aumenta el tamaño de las páginas. Además, la E/S de disco es más eficiente cuando la cantidad de datos transferidos es mayor.

Un aspecto importante de la paginación es la clara separación entre la visión del programador de la memoria y la memoria física real. El programador ve la memoria como un único espacio, que contiene solo su programa. En realidad, el programa del usuario está disperso por toda la memoria física, que también contiene otros programas. La diferencia entre la visión del programador de la memoria y la memoria física real se reconcilia mediante el hardware de traducción de direcciones.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
26
Q

¿Qué es un page fault y cómo se resuelve?

A

¿qué sucede si el proceso intenta acceder a una página que no se ha traído a la memoria? El acceso a una página marcada como inválida provoca una falla de página. El hardware de paginación, al traducir la dirección a través de la tabla de páginas, notará que el bit de inválido está establecido, provocando una interrupción al sistema operativo. Esta interrupción es el resultado de la falta del sistema operativo para traer la página deseada a la memoria. El procedimiento para manejar esta falla de página es sencillo:

Verificamos una tabla interna (generalmente mantenida con el bloque de control de proceso) para este proceso para determinar si la referencia fue un acceso a memoria válido o inválido.
Si la referencia fue inválida, terminamos el proceso. Si fue válida pero aún no hemos traído esa página, la traemos ahora.
Encontramos un marco libre (tomando uno de la lista de marcos libres, por ejemplo).
Programamos una operación de almacenamiento secundario para leer la página deseada en el marco recién asignado.
Cuando la lectura del almacenamiento se completa, modificamos la tabla interna mantenida con el proceso y la tabla de páginas para indicar que la página ahora está en memoria.
Reiniciamos la instrucción que fue interrumpida por la interrupción. El proceso ahora puede acceder a la página como si siempre hubiera estado en memoria.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
27
Q

¿Por qué puede pasar que tengamos muchos procesos en waiting, y cómo podría tratar de arreglarlo si no pudiese agregar memoria?

A

Matar algunos procesos para poder tener más espacio de memoria.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
28
Q

Hablar de RAID (para qué sirve). Explicar la diferencia entre RAID 4 y RAID 5. ¿Cuál es mejor y por qué?

A

RAID (Redundant Array of Independent Disks) es una tecnología de almacenamiento que combina múltiples discos duros para mejorar el rendimiento y/o la redundancia de datos. RAID 4 y RAID 5 son dos tipos específicos de configuraciones RAID, cada una con sus propias características y beneficios.

RAID 4
RAID 4 utiliza el striping de datos (división de datos en tiras) similar a RAID 0, pero con la adición de un disco dedicado para la paridad. La paridad es información de corrección de errores que permite la reconstrucción de datos en caso de fallo de un disco. En RAID 4:

Datos y paridad: Los datos se dividen en bloques y se distribuyen entre los discos, mientras que un disco específico se dedica exclusivamente a almacenar la información de paridad.
Rendimiento de lectura: La lectura puede ser rápida ya que los datos se pueden leer de múltiples discos simultáneamente.
Rendimiento de escritura: Las escrituras son más lentas que en RAID 0 porque cada vez que se escribe un bloque de datos, se debe actualizar el disco de paridad.
Capacidad de recuperación: Si un disco de datos falla, los datos pueden ser reconstruidos utilizando la información de paridad almacenada en el disco dedicado.
RAID 5
RAID 5 también utiliza el striping de datos, pero en lugar de tener un disco dedicado a la paridad, distribuye la paridad entre todos los discos del arreglo. En RAID 5:

Datos y paridad distribuida: Los datos y la paridad se distribuyen entre todos los discos, lo que evita el cuello de botella de tener un solo disco de paridad.
Rendimiento de lectura: Es alto, similar a RAID 4, ya que los datos se pueden leer de múltiples discos simultáneamente.
Rendimiento de escritura: Mejor que RAID 4 en la mayoría de los casos, ya que la paridad no se encuentra en un solo disco, aunque aún es más lento que RAID 0 debido a la necesidad de calcular y escribir la paridad.
Capacidad de recuperación: Si un disco falla, los datos pueden ser reconstruidos utilizando la paridad distribuida en los otros discos.
Comparación
Rendimiento: RAID 5 generalmente ofrece un mejor rendimiento de escritura que RAID 4 debido a la distribución de la paridad.
Redundancia: Ambos proporcionan redundancia para fallos de un solo disco, pero RAID 5 es más eficiente en términos de utilización del espacio de almacenamiento, ya que no dedica un disco completo a la paridad.
Coste: RAID 5 puede ser más rentable porque no requiere un disco adicional dedicado exclusivamente a la paridad.
En resumen, RAID 4 y RAID 5 ofrecen formas de mejorar la redundancia y el rendimiento del almacenamiento, pero RAID 5 es más popular debido a su mejor equilibrio entre rendimiento y uso del espacio de almacenamiento.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
29
Q

Explicar los distintos algoritmos básicos de scheduling de disco. Explicar cómo se comportan en HDD y en SDD.

A

El scheduling de disco es el proceso de decidir el orden en que se atenderán las solicitudes de lectura/escritura en un disco. Existen varios algoritmos básicos de scheduling de disco que se utilizan para optimizar el rendimiento y minimizar la latencia. Aquí se explican algunos de los algoritmos más comunes y cómo se comportan en discos duros (HDD) y unidades de estado sólido (SSD).

Algoritmos Básicos de Scheduling de Disco
First-Come, First-Served (FCFS):

Descripción: Atiende las solicitudes en el orden en que llegan.
Comportamiento en HDD: Puede resultar en tiempos de espera largos si las solicitudes están desordenadas, ya que el cabezal del disco puede tener que moverse de un extremo a otro repetidamente.
Comportamiento en SSD: Menos impactante, ya que no hay movimientos físicos de cabezal. Sin embargo, puede no ser óptimo en términos de latencia si las solicitudes están distribuidas aleatoriamente.
Shortest Seek Time First (SSTF):

Descripción: Atiende la solicitud más cercana a la posición actual del cabezal.
Comportamiento en HDD: Mejora el rendimiento en comparación con FCFS al minimizar el movimiento del cabezal. Sin embargo, puede llevar a la inanición de solicitudes lejanas.
Comportamiento en SSD: La proximidad física no es relevante, pero puede mejorar el rendimiento agrupando solicitudes cercanas en términos de direcciones de bloques.
SCAN (Elevator Algorithm):

Descripción: El cabezal del disco se mueve en una dirección atendiendo todas las solicitudes hasta llegar al final, luego invierte la dirección.
Comportamiento en HDD: Reduce significativamente los tiempos de espera en comparación con FCFS y SSTF, ya que el cabezal sigue una trayectoria más sistemática.
Comportamiento en SSD: No aporta beneficios significativos, pero sigue siendo eficiente en la organización de las solicitudes.
C-SCAN (Circular SCAN):

Descripción: Similar a SCAN, pero en lugar de invertir la dirección, el cabezal vuelve al principio sin atender solicitudes en el camino de regreso.
Comportamiento en HDD: Proporciona tiempos de espera más uniformes que SCAN, especialmente para solicitudes en extremos opuestos del disco.
Comportamiento en SSD: Igual que SCAN, no aporta beneficios significativos en SSD pero mantiene una organización eficiente.
LOOK y C-LOOK:

Descripción: Variaciones de SCAN y C-SCAN que se detienen en la última solicitud en lugar de ir hasta el final del disco.
Comportamiento en HDD: Optimiza aún más el movimiento del cabezal al evitar movimientos innecesarios.
Comportamiento en SSD: Similar a SCAN y C-SCAN, la optimización es marginal debido a la ausencia de movimiento físico del cabezal.
Comportamiento en HDD y SSD
HDD (Hard Disk Drive)
Movimientos físicos: Los HDD tienen cabezales de lectura/escritura que se mueven físicamente sobre platos giratorios. El tiempo de búsqueda (seek time) y el tiempo de latencia rotacional son factores críticos que afectan el rendimiento.
Optimización de movimiento: Algoritmos como SSTF, SCAN y LOOK son efectivos para minimizar el movimiento del cabezal y reducir los tiempos de búsqueda, mejorando el rendimiento general.
SSD (Solid State Drive)
Sin movimientos físicos: Los SSD no tienen partes móviles, lo que elimina el tiempo de búsqueda y latencia rotacional.
Acceso aleatorio rápido: Los SSD tienen tiempos de acceso aleatorio muy bajos, por lo que la mayoría de los algoritmos de scheduling no tienen un impacto tan significativo en el rendimiento como en los HDD.
Eficiencia de procesamiento: Aunque los algoritmos pueden seguir agrupando solicitudes para optimizar el procesamiento, la diferencia en rendimiento entre algoritmos es menos pronunciada en SSD.
Resumen
FCFS: Sencillo pero puede ser ineficiente en HDD; menos crítico en SSD.
SSTF: Reduce tiempos de búsqueda en HDD; mejora marginal en SSD.
SCAN/C-SCAN: Proporcionan una mejora considerable en HDD; mantienen eficiencia en SSD.
LOOK/C-LOOK: Optimización adicional en HDD; comportamiento similar a SCAN en SSD.
En general, los algoritmos de scheduling de disco tienen un impacto más significativo en HDD debido a los movimientos físicos involucrados, mientras que en SSD, donde no hay partes móviles, la mejora en el rendimiento es menor.

30
Q

¿Qué son los drivers y qué permiten?

A

Los drivers son componentes de software muy específicos. Conocen las particularidades del HW contra el que hablan.Incluso distintos modelos de un mismo fabricante pueden requerir distintos drivers.
Los drivers son clave.Corren con máximo privilegio: pueden hacer colgarse a todo elsistema.De ellos depende el rendimiento de E/S, que es fundamental para el rendimiento combinado del sistema.

31
Q

Polling

A

El driver periódicamente verifica si el dispositivo se comunicó.
Ventajas: sencillo, cambios de contexto controlados.
Desventajas: Consume CPU.

32
Q

Interrupciones (o push)

A

El dispositivo avisa (genera una interrupción).
Ventajas: eventos asincrónicos poco frecuentes.
Desventajas: cambios de contexto impredecibles.

33
Q

DMA (acceso directo a memoria)

A

Para transferir grandes volúmenes (la CPU no interviene).
Requiere de un componente de HW, el controlador de DMA.Cuando el controlador de DMA finaliza, interrumpe a la CPU.

34
Q

Explicar las diferencias entre un disco magnético y un SSD. ¿Qué problemas tiene un SDD? Hablar de write amplification y borrado.

A

Discos Magnéticos (hdd): Son la mayor parte del sistema de memoria secundario en las computadoras modernas. Un disco rígido, consiste en un conjunto de platos (platters) con una forma circular y varios cabezales de lectura-escritura (read-write head) que “vuelan”sobre su superficie: Todos los cabezales están unidos a un brazo que los mueve de manera unísona. Cuando undisco está en uso, un motor gira sus platos a alta velocidad y el brazo mueve los cabezales de manera radial (desde el centro del plato hasta el perímetro del mismo y viceversa). La superficie de cada plato está divida en sectores lógicos llamados tracks que están subdivido en sectores. El conjunto de tracks que estan a la misma distancia del brazo se llama cilindro. Cada disco puede tener miles de cilindros y cada track cientos de sectores por lo que en general la capacidad de estos dispositivos se mide en gigabytes. La velocidad de un disco se divide en dos partes:
Velocidad de transferencia (Transference Rate): La velocidad a la que la infromación viaja entre el disco y la computadora.
Tiempo de posicionamiento (random-acces time): Que es el tiempo que tarda el disco en encontrar un sector determinado. Este tiempo se puede dividir en dos partes:
Tiempo de búsqueda (seek time): El tiempo necesario para mover el cabezal al cilindro adecuado.
Latencia rotacional (Rotational Latency): El tiempo necesario para que el sector llegue al cabezal ya posicionado
Generalmente, los discos pueden transferir varios megabytes de datos por segundo y los tiempos
de búsqueda y de giro toman varios milisegundos. Un disco puede ser removible permitiendo que varios discos se vayan montando y desmontandona medida que sea necesario. Algunas formas de discos removibles incluyen: CDs, DVDs y BluRays y memorias flash.
Disco Sólido(SSD): Un disco de estado sólido es una memoria no volátil que es usada como disco rígido. Tienen las mismas características que los discos clásicos pero son más seguros porque no tienen partes mobiles y son más rápidos por que no tienen latencia y ni tiempo de búsqueda. Además, consumen menos energía. Sin embargo, son más caros que los discos tradicionales, tienen menos capacidad y tiempos de vida más cortos. Otro problema que tiene este tipo de discos es llamado write amplification, en el cual la cantidad de información escrita en el disco es un múltiplo de la cantidad lógica que se intentó escribir. En las memorias flash, es necesario borrar la memoria antes de poder escribirla pero las operaciones de borrado tienen una granularidad bastante mayor a la de escritura. Entonces, el proceso de escribir a memoria, muchas veces implica mover la sección usada de un bloque a alguna ubicación no usada del disco y luego borrar todo el bloque para luego poder escribir en la ubicación deseada. Osea que una escritura puede requerir que se lea, actualize y reescriba alguna parte de la memoria ya utilizada en una nueva ubicación. Borrar la ubicación inicial y luego escribir los datos que se desean guardar. Este efecto multiplicador aumenta la cantidad de escrituras necesarias en el disco, lo que acorta el tiempo que puede funcionar de manera confiable.

35
Q

¿Qué es un file descriptor? Nombrar 3 system calls que los afecten.

A

Un file descriptor es un identificador abstracto utilizado en sistemas operativos tipo Unix y similares para acceder a archivos y otros recursos de entrada/salida, como sockets y pipes. Cuando un programa abre un archivo o crea un recurso de I/O, el sistema operativo le asigna un número entero único que actúa como un índice en una tabla de descriptores de archivos gestionada por el kernel. Este número es el file descriptor.

Características de un File Descriptor
Identificador único: Cada file descriptor es un número entero que es único dentro del contexto del proceso que lo posee.
Tabla de descriptores: El kernel mantiene una tabla de descriptores de archivos para cada proceso, donde cada entrada contiene información sobre el archivo o recurso asociado (como la posición actual de lectura/escritura, permisos, etc.).
Tres System Calls que Afectan File Descriptors
open:

Descripción: Abre un archivo y retorna un file descriptor que puede ser utilizado para realizar operaciones de lectura y escritura.
Sintaxis: int open(const char *pathname, int flags, mode_t mode);
Ejemplo:
c
Copy code
int fd = open(“example.txt”, O_RDONLY);
if (fd == -1) {
// Manejar error
}
read:

Descripción: Lee datos desde un archivo o recurso referenciado por un file descriptor.
Sintaxis: ssize_t read(int fd, void *buf, size_t count);
Ejemplo:
c
Copy code
char buffer[100];
ssize_t bytesRead = read(fd, buffer, sizeof(buffer));
if (bytesRead == -1) {
// Manejar error
}
close:

Descripción: Cierra un file descriptor, liberando el recurso asociado y eliminando el descriptor de la tabla del proceso.
Sintaxis: int close(int fd);
Ejemplo:
c
Copy code
if (close(fd) == -1) {
// Manejar error
}

36
Q

¿Qué es un FS y para qué sirve?

A

Existe un módulo dentro del kernel encargado de organizar la información en disco: sistema de archivos o file system.

37
Q

¿Cuál FS nos conviene utilizar para un sistema embebido: FAT o inodos?

A

Si tu sistema embebido tiene recursos muy limitados y la compatibilidad es una prioridad, FAT es probablemente la mejor opción. Sin embargo, si la fiabilidad y la integridad de los datos son más importantes y tu sistema puede manejar la complejidad adicional, un sistema basado en inodos sería más beneficioso.

38
Q

¿Cuál FS nos conviene utilizar para implementar un backup total? ¿Cómo se implementaría en FAT y en inodos?

A

Para el backup total conviene FAT, porque se puede ver rápidamente en la FAT los bloques ocupados de disco. Con inodos tendrías que mirarlos todos.

39
Q

¿Cuál FS nos conviene utilizar para implementar un backup incremental? ¿Cómo se implementaría en FAT y en inodos?

A

FAT (File Allocation Table)
Ventajas:
Alta compatibilidad con múltiples sistemas operativos.
Estructura simple y fácil de manejar.
Desventajas:
Falta de características avanzadas como journaling y atributos extendidos.
Menor capacidad para manejar metadatos detallados, dificultando la implementación eficiente de backups incrementales.
Sistemas basados en inodos (como ext2, ext3, ext4)
Ventajas:
Soporte para atributos extendidos, mejor gestión de metadatos.
Journaling (en ext3/ext4), mejorando la fiabilidad y recuperación de datos.
Capacidad para manejar archivos grandes y un gran número de archivos.
Desventajas:
Más complejos y pueden requerir más recursos del sistema.
Recomendación
Para implementar un backup incremental, ext3 o ext4 es más adecuado debido a su capacidad de manejar metadatos detallados y atributos extendidos, lo que facilita el seguimiento de cambios en los archivos.

40
Q

Explicar las diferencias entre FAT e inodos. Ventajas y desventajas de cada uno.

A

FAT tiene una tabla donde guarda para cada bloque el siguiente bloque del directorio.
Ventajas:Tiene todos los bloques en memoria y no desperdicia espacio de bloque. Es más eficiente que la lectura no secuencial.
Desventajas: es inmanejable para disco grandes. Como hay una única tabla hay mucha contención. Es poco robusto porque si se cae el sistema, se cae la tabla que estaba en memoria y no maneja seguridad.
INODOS hay un indo por cada archivo. En las primeras entradas de esté hay atributos. Sigue una entrada que apunta a un bloque llamados single indirect block. En este bloque hay punteros a bloques de datos. Eso sirve para archivos de hasta 16 MB.A continuación una entrada llamada double indirect block,que apunta a una tabla de single indirect blocks. Con eso se cubren archivos de hasta 32 GB.Le sigue un triple indirect block, que apunta a un bloque de double indirect blocks. Eso cubre hasta 70 TB.

Ventajas: Sirve para discos grandes. Permite tener en memoria solo las tablas correspondientes a los archivos abiertos. Hay una tabla por archivo, mucha menos contención. Es más consistente, ya que solo están en memoria las listas correspondientes a los archivos abiertos.

41
Q

¿FAT implementa algún tipo de seguridad?

A

no, no implementa ninguna seguridad

42
Q

Explicar qué es journaling

A

Journaling es una técnica utilizada en sistemas de archivos para mejorar la fiabilidad y la integridad de los datos. Se trata de registrar cambios previstos en un diario (journal) antes de que se realicen realmente en el sistema de archivos. Este proceso permite una recuperación más rápida y segura de los datos en caso de fallos del sistema, como un corte de energía o un bloqueo del sistema.

Cómo Funciona el Journaling
Registro en el Journal:

Cuando se va a realizar una operación que modifica el sistema de archivos (como crear, eliminar o modificar un archivo), los cambios previstos se escriben primero en una zona especial del disco llamada journal.
Este registro incluye información sobre qué cambios se van a realizar y cómo se deben aplicar.
Aplicación de Cambios:

Después de que los cambios se hayan registrado en el journal, se aplican realmente al sistema de archivos.
Una vez que los cambios se han aplicado con éxito, se marca el registro correspondiente en el journal como completado.
Borrado del Journal:

Los registros de cambios completados pueden ser eliminados del journal, liberando espacio para nuevos registros.
Ventajas del Journaling
Integridad de Datos:

En caso de un fallo del sistema, el journal puede ser utilizado para recuperar y completar cualquier operación incompleta, asegurando que el sistema de archivos quede en un estado consistente.
Recuperación Rápida:

La recuperación después de un fallo es más rápida porque el sistema solo necesita revisar el journal para completar o revertir las operaciones pendientes, en lugar de verificar todo el sistema de archivos.
Reducción de Corrupción:

Disminuye la probabilidad de corrupción del sistema de archivos al asegurar que todas las operaciones de modificación sean atómicas (completas o no realizadas en absoluto).
Tipos de Journaling
Journaling de Metadatos:

Solo los cambios en los metadatos (estructura del sistema de archivos) se registran en el journal. Los datos del archivo en sí no se registran.
Ejemplos: ext3, ext4 en modo de journaling de metadatos.
Journaling Completo:

Tanto los cambios en los metadatos como en los datos de los archivos se registran en el journal.
Más seguro pero puede ser más lento y consumir más espacio en el journal.
Journaling por Orden:

Solo los metadatos se registran en el journal, pero se asegura que los datos del archivo se escriban en el disco antes de que se registren los cambios en los metadatos.
Ejemplos: ext4 en modo de journaling por orden.
Ejemplos de Sistemas de Archivos con Journaling
ext3/ext4: Sistemas de archivos basados en inodos para Linux que soportan journaling de metadatos y journaling por orden.
NTFS: Sistema de archivos de Windows que utiliza journaling para asegurar la integridad de los datos.
HFS+: Sistema de archivos de Apple que incluye soporte para journaling.
Resumen
El journaling es una técnica que mejora la integridad y la fiabilidad de los sistemas de archivos al registrar las operaciones previstas en un diario antes de aplicarlas. Esto permite una recuperación rápida y segura de los datos en caso de fallos del sistema, y reduce la probabilidad de corrupción del sistema de archivos. Diferentes tipos de journaling proporcionan distintos niveles de seguridad y rendimiento, siendo común en sistemas de archivos modernos como ext3, ext4 y NTFS.Hay un registro de los cambios que habría que hacer.Eso se graba en un buffer circular. Cuando se baja el caché a disco, se actualiza una marca indicando qué cambios ya sereflejaron.Si el buffer se llena, se baja el cache a disco.Hay un impacto en performance pero es bajo porque:Este registro se escribe en bloques consecutivos, y una escritura secuencial es mucho más rápida que una aleatoria.Los FS que no hacen journal escriben a disco inmediatamente los cambios en la metadata, para evitar daños mayores en los archivos.Cuando el sistema levanta, se aplican los cambios aún no aplicados. Esto es mucho más rápido que recorrer todo el disco.

43
Q

¿Qué mantiene un inodo? ¿Cómo es la estructura de directorios?

A

Mantengo indexados todos los bloques de cada archivo en un inodo. Un inodo es una tabla que tiene atributos y bloques (single indirect block). En este bloque hay punteros a bloques de datos. Eso sirve para archivos de hasta 16 MB. Luego tenemos double indirect block que apunta a una tabla de single indirect blocks. Con eso se cubren archivos de hasta 32 GB. Le sigue un triple indirect block, que apunta a un bloque de double indirect blocks. Eso cubre hasta 70 TB.
Los directorios se almacenan en disco como archivos comunes,aunque su contenido se interpreta diferente. Se los distingue por el tipo de archivo.A cada directorio le corresponde un inodo, y cada bloque de un directorio es una lista de entradas de directorio(dentry). Cada entrada a su vez contiene la longitud de la entrada, el nombre del archivo, y el número de inodo al que refiere. El resto de metadatos están en cada inodo. Las primeras dos entradas en todos los directorios son ‘‘.’’y ‘‘..’’. Al igual que en FAT, el inodo del directorio root es distinguido.

44
Q

¿Para qué sirven los block groups y los clusters? Motivación para agrupar páginas en bloques, y bloques en grupos de bloques.

A

Para saber más fácilmente donde empiezan los bloques vacíos.

45
Q

¿Cuáles son las estructuras más importantes de ext2? Explicar cada una (en particular, hablar del superbloque).

A

Están los inodos, que contienen bloques con atributos y datos. Uno de estos bloques es el super bloque que contiene metadatos críticos del sistema de archivos tales como información acerca del tamaño, cantidad de espacio libre y donde se encuentran los datos. Si el superbloque es dañado, y su información se pierde, no podría determinar que partes del sistema de archivos contiene información. Después contiene la tabla de inodos que contiene un por cada inodo su inodo y su nombre de archivos. Y después tiene la tabla de datos.

46
Q

Explicar cómo se manejan los bloques libres del disco.

A

Otro problema es cómo manejar el espacio libre.Una técnica posible es utilizar un mapa de bits empaquetado,donde los bits en 1 significan libre.As´ı, si una palabra tiene todos 0 puedo saltearla por completo con una única comparación.Pero requiere tener el vector en memoria, y eso no est´a bueno.También podemos tener una lista enlazada de bloques libres.En general se clusterizar. Es decir, si un bloque de disco puede contener n punteros a otros bloques, los primeros n − 1 indican bloques libres y el último es el puntero al siguiente nodo de la lista.Un refinamiento consiste en que cada nodo de la lista indique,además del puntero, cuantos bloques libres consecutivos hay a partir de él.

47
Q

¿Qué pasa cuando se inicia el sistema luego de haber sido apagado de forma abrupta? Explicar cómo hace el sistema para darse cuenta de si hubo algún error (cuando no hace journaling) y cómo lo arregla. (inconsistencias entre contadores y bitmaps, entre entradas de inodos y bitmaps, entre entradas de directorios y bitmaps)

A

Cuando un sistema se apaga abruptamente sin usar journaling, pueden surgir inconsistencias en el sistema de archivos. La herramienta fsck (File System Consistency Check) se usa para detectar y corregir estas inconsistencias.

Inconsistencias Comunes y Corrección
Entre Contadores y Bitmaps:

Inconsistencia: Los contadores que indican el número de bloques e inodos libres no coinciden con los bitmaps.
Corrección: fsck verifica los bitmaps y actualiza los contadores en el superblock para reflejar correctamente el estado de los bitmaps.
Entre Entradas de Inodos y Bitmaps:

Inconsistencia: Un inodo está marcado como libre en el bitmap pero contiene datos, o está marcado como en uso pero está vacío.
Corrección: fsck recorre todos los inodos y ajusta el bitmap o libera el inodo según sea necesario.
Entre Entradas de Directorios y Bitmaps:

Inconsistencia: Una entrada de directorio apunta a un inodo marcado como libre en el bitmap, o un inodo en uso no tiene ninguna entrada en directorios.
Corrección: fsck verifica todas las entradas de directorios y ajusta las entradas o los bitmaps para asegurar que todos los inodos en uso estén correctamente referenciados y los inodos sin referencias sean liberados.

48
Q

Explicar las diferencias (ventajas y desventajas) entre soft links y hard links. ¿Por qué no podemos usar un hard link para referenciar inodos de otro FS, incluso si está basado en inodos?

A

Hard link
Supongamos un sistema de archivos basado en inodos que soporta hard links (con FAT es similar). Un sistema de archivos de este tipo permite tener más de una entrada de directorio (dir entry) apuntando al mismo inodo de un archivo. Estos dir entry son los hard links. En efecto, un inodo podría tener más de un nombre en más de un directorio (recuerden que el nombre del inodo está en el dir entry). Para que esto funcione, el inodo debe tener un contador de hard links en su estructura. Cada vez que se borra un hard link se decrementa ese contador y el inodo se borra solamente cuando ese contador llega a cero. No hay un hard link distinguido para un inodo, simplemente hay uno que se crea primero (cuando se crea el archivo). Todos los hard links de un inodo son iguales.
Soft link
Un soft link es una entrada de directorio que apunta a otra entrada de directorio referenciada por su camino (absoluto o relativo). El link no se hace a nivel de inodo, sino que se hace a nivel de entrada de directorio. En general, en este tipo de links no se guarda un contador de referencias en los dir entries. Por lo que un soft link se puede romper muy fácil si el elemento referenciado es movido, renombrado o borrado. En cualquiera de estos casos el soft link seguirá existiendo pero apuntará a un camino que ya no existe y por lo tanto estará “roto”.

49
Q

¿Qué es un sistema distribuido? ¿Qué significa que un sistema sea completamente distribuido? ¿Qué beneficios ofrecen? ¿Qué problemas nos puede traer?

A

conjunto de nodos conectados en una red
En un sistema de cómputo distribuido tenemos varias computadoras autónomas que interactuan entre si a las cuales abstraemos como un unico sistema a la vista del usuario.
Ejemplos
Conjunto de recursos conectados que interactúan.
Varias máquinas conectadas en red.
Un procesador con varias memorias.
Varios procesadores que comparten una (o más) memoria(s).
Fortalezas: Paralelismo, Replicación, Descentralización.
Debilidades:
Dificultad para la sincronización.
Dificultad para mantener coherencia.
No suelen compartir clock.
Información parcial.

50
Q

Explicar los distintos algoritmos de commits que se utilizan para actualizar una copia del archivo que está en varios nodos (2PC y 3PC). ¿Cuál es la diferencia entre 2PC y 3PC? Explicar la diferencia entre weak/strong termination.

A

2PC(Two Phase Commit)
La idea es realizar una transacción de manera atómica. Todos debemos estar de acuerdo en que se hizo o no se hizo. El espiritu es que en una primera fase le preguntamos a todos si están de acuerdo en que se haga la transaccion. Si recibimos un no, abortamos. Si recibimos un si, vamos anotando los que dijeron que si. Si pasado un tiempo máximo no recibimos todos los si, también abortamos. Si recibimos todos los sí, ahí avisamos a todos que quedó confirmada (esta sería la segunda fase). No protege contra todas las fallas, pero sí contra muchas.

(def práctica) Supongamos que tenemos un nodo lider. Como el nombre del algoritmo dice, tenemos dos fases.
Fase Commit Request: En esta fase se pregunta si se puede realizar la operacion pedida
Paso 1: El lider le envia a todos los nodos un mensaje con el commit correspondiente y les pregunta si se puede realizar la operación pedida.
Paso 2: Los nodos receptores reciben el mensaje y proceden a ejecutar lo pedido, lockeando los recursos que tienen que utilizar. Sin embargo, no hacen ”commit”, sino que guardan en una tabla el proceso de como deshacer los cambios hechos.
Paso 3: Cada nodo contesta con un mensaje ”OK” en caso de exito en su operacion o ”ABORT” si hubo alg´un fallo.
Fase de completacion (exito):
Paso 1: En caso que todos los nodos contestaron con ”OK”, entonces el lider envia a todos los nodos el mensaje de ”commit”.
Paso 2: Cada nodo receptor completa su operacion, liberando los recursos y el lock. I
Paso 3: Cada nodo envia ”COMMIT OK” al lider.
Paso 4: El lider da por finalizado el proceso en caso de recibir ”COMMIT” de todos los nodos.
Fase de completacion (Fallo):
Paso 1: En caso que al menos un nodo contestara con ”ABORT”, se procede a enviar un mensaje de ”rollback” a todos los nodos
Paso 2: Cada nodo receptor procede a deshacer su operacion, usando la tabla que uso en la fase anterior, luego liberando los recursos y unlockeando.
Paso 3: Cada nodo envia ”COMMIT OK” al lider.
Paso 4: El lider da por finalizado el proceso comunicando el fallo.

3PC(Resuelve terminación fuerte): Igual que 2PC, pero se agrega una nueva fase entre las dos fases del algoritmo anterior.
Paso 1: igual que 2PC
Paso 2 :Proceso lider junta todos los valores que recibió, si hay algun ”ABORT” decide enviar a todos el mensaje de aborto y terminar el proceso. Si no manda un mensaje para que los otros procesos se pongan en ‘Prepare to commit‘. I Los nodos contestan si estan preparados para commitear o no
Paso 3 es igual a 2PC

Si el lider muere en la primera fase o segunda fase:
Se elije un nuevo lider (de alguna forma) y se puede abortar la ejecucion o reiniciar al algoritmo sin el lider anterior. No necesariamente tiene que tener respuesta de todos los procesos (algunos más pueden haber fallado). Si alguien decidió ABORTAR entonces el nuevo lider decide ABORT y le manda este mensaje a todos.
Si el lider muere en la ultima fase:
Se elije un nuevo lider (de alguna forma) y le pregunta a los otros nodos en que estado estan. Si un solo nodo dice que esta en el estado de ”commit inicialized”, entonces se asume que el lider anterior habia decidio pasar a la ultima fase, con lo cual se puede continuar el protocolo sin abortar.

51
Q

¿Qué hace un nodo si se cae después de que todos digan sí al coordinador en 2PC?

A

Si el lider muere en la ultima fase:
Se elije un nuevo lider (de alguna forma) y le pregunta a los otros nodos en que estado estan. Si un solo nodo dice que esta en el estado de ”commit inicialized”, entonces se asume que el lider anterior habia decidio pasar a la ultima fase, con lo cual se puede continuar el protocolo sin abortar.

52
Q

Explicar el problema bizantino

A

Acuerdo bizantino: Las distintas divisiones del ejército bizantino rodean una ciudad, desde distintas comarcas. Solo pueden ganar si atacan todos juntos, así que deben coordinar el ataque. Sólo se pueden comunicar mediante mensajeros que corren de un lugar a otro, pero pueden ser interceptados. Versión más complicada: pueden ser sobornados. Cómo sabemos que el mensaje llego al otro lado? Entramos en un loop infinito de mandar al mensajero ida y vuelta avisando.
Version: Los mensajes pueden perderse

TEOREMA: No existe ningún algoritmo para resolver consenso en este escenario.
Version: Los nodos pueden morir

Versión más complicada: los mensajeros pueden ser sobornados.

53
Q

¿Qué es un file system distribuido? Explicar la interfaz VFS.

A

Distributed File System (DFS): un sistema de archivos cuyos clientes, servidores y dispositivos de almacenamiento están distribuidos entre las máquinas de un sistema distribuido.
Un sistema de archivos distribuidos es un sistema que provee servicios de archivos (abrir, leer, escribir, cerrar, etc) a sus clientes. Con la particularidad, de que los archivos están repartidos entre todas las máquinas de una red. La interfaz del cliente no debería distinguir entre archivos locales y remotos. Es deber del DFS localizar el archivo y gestionar el transporte de datos.

54
Q

¿NFS es un file system completamente distribuido?

A

NFS no es un sistema de archivos completamente distribuido en el sentido más estricto. Es un sistema de archivos distribuido en el sentido de que permite el acceso remoto a archivos a través de la red, pero sigue una arquitectura cliente-servidor con centralización en el servidor. Para lograr un sistema de archivos completamente distribuido, se necesitaría una solución que distribuya la carga de almacenamiento y gestión de archivos entre múltiples nodos.

55
Q

Proponer una manera para mantener sincronizados N servidores NFS. Explicar cómo saben los nodos a qué servidor pedirle los datos

A

Los clientes se conectar al servidor de metadata y hay varios servidores de datos que contienen chunks (porciones) de archivos. El servidor de metadata mantiene un mapeo de que servidores de datos tienen chunks de cada archivo. Los chunks de cada archivo se replican n veces.

56
Q

Explicar cómo son las ACLs en UNIX.

A

Los permisos se aplican sobre elementos del sistema de archivos, tales como archivos regulares, directorios, sockets Unix, enlaces simbólicos, nodos de dispositivos, etc. Los tipos de permisos que puede administrar GNU/Linux, o permisos POSIX, son tres:
Lectura (r: Read): la entidad asociada podrá leer el elemento.
Escritura (w: Write): la entidad asociada podrá escribir o modificar el elemento.
Ejecución (x: eXecution): la entidad asociada podrá ejecutar el elemento.
Las entidades sobre las que tienen vigencia estos permisos son:
Usuario dueño (u: User): usuario dueño del elemento en el sistema de archivos.
Grupo al que pertenece (g: Group): grupo al que pertenece el elemento.
Otros usuarios (o: Others): el resto de los usuarios del sistema que no son ni el dueño del elemento, ni pertenecen al grupo del elemento.
Las listas de control de acceso (ACLs) nos permiten aplicar un conjunto más específico de permisos a un archivo o directorio sin (necesariamente) cambiar la propiedad y los permisos base. Nos permiten “añadir” acceso para otros usuarios o grupos.

El esquema más general para implementar el acceso dependiente de la identidad es asociar a cada archivo y directorio una lista de control de acceso (ACL) que especifique los nombres de los usuarios y los tipos de acceso permitidos para cada usuario. Cuando un usuario solicita acceso a un archivo en particular, el sistema operativo verifica la lista de acceso asociada con ese archivo. Si ese usuario está listado para el acceso solicitado, se permite el acceso. De lo contrario, se produce una violación de protección y se le niega el acceso al archivo al usuario.

57
Q

Explicar cómo funcionan los canarios, DEP y ASLR .

A

Los stack canaries se usan para tratar de detectar la sobreescritura de la dirección de retorno en el stack por un buffer overflow. Son un valor generado aleatoriamente con cada ejecución de un programa y que se pushea al stack luego de la dirección de retorno, entre esta y el buffer que puede ser atacado. Luego, antes de retornar de cada llamado a una función, el programa verifica que el stack canary no haya sido modificado. Si lo fue, hubo un buffer overflow y se debe abortar la ejecución sin retornar.

Las desventajas de los stack canaries son:
- Dado que son generados por el compilador, sólo sirven para programas que son compilados con ellos. No sirven para proteger programas que no fueron compilados con stack canaries, a diferencia de técnicas como stack randomization.
- El valor del stack canary suele ser definido al iniciar la ejecución del programa y mantenerse fijo. Cuando un proceso hace un fork, el proceso hijo hereda el valor del stack canary. Esto puede dar lugar a ataques de fuerza bruta sobre el canary. Por ejemplo, un proceso de un servidor web puede forkear un proceso para atender a cada request entrante. Si el atacante puede hacer un buffer overflow con este proceso hijo, puede sobrescribir byte por byte el stack canary y ver si el proceso aborta o no para adivinar el valor.
- Dado que el programa debe pushear y verificar el stack canary en cada llamado a función, y que los programas suelen tener una cantidad importante de llamados a funciones durante su ejecución, el rendimiento del programa puede ser afectado.

No se si es desventaja de usar stack canaries, pero el hecho de usarlo no implica que dejen de existir los buffer overflow. En el tanenbaum hay un ejemplo donde se saltea la modificación del stack canary y aún así puede modificar la dirección de retorno

DEP: Ninguna región de memoria deberıa ser al mismo tiempo escribible y ejecutable.Ejemplos básicos: Heap y Stack.Se implementan con ayuda del hardware, por ejemplo, bit NX(en Intel).Impide algunos ataques básicos (como que ya no se puede inyectar código).Hay técnicas para “bypassear” esta protección:

ROP (Return-Oriented Programming)

El concepto de ROP (Programación Orientada a Retornos) lleva la idea de reutilizar el código del programa al extremo. En lugar de retornar a (los puntos de entrada de) funciones de la biblioteca, el atacante puede retornar a cualquier instrucción en el segmento de texto. Por ejemplo, puede hacer que el código llegue a la mitad, en lugar del principio, de una función. La ejecución simplemente continuará en ese punto, una instrucción a la vez. Supongamos que después de un puñado de instrucciones, la ejecución encuentra otra instrucción de retorno. Ahora, hacemos la misma pregunta una vez más: ¿a dónde podemos retornar? Dado que el atacante tiene control sobre la pila, puede nuevamente hacer que el código retorne a cualquier lugar que desee. Además, después de haberlo hecho dos veces, también puede hacerlo tres veces, o cuatro, o diez, etc. Por lo tanto, el truco de la programación orientada a retornos es buscar pequeñas secuencias de código que (a) hagan algo útil, y (b) terminen con una instrucción de retorno. El atacante puede encadenar estas secuencias mediante las direcciones de retorno que coloca en la pila. Los fragmentos individuales se llaman gadgets. Típicamente, tienen una funcionalidad muy limitada, como sumar dos registros, cargar un valor de la memoria en un registro o empujar un valor en la pila. En otras palabras, la colección de gadgets puede verse como un conjunto de instrucciones muy extraño que el atacante puede usar para construir funcionalidad arbitraria mediante la manipulación inteligente de la pila. Mientras tanto, el puntero de la pila sirve como un tipo de contador de programa ligeramente extraño.

ASLR: Modifica de manera aleatoria la dirección base de regiones
importantes de memoria entre las diferentes ejecuciones de un
proceso Por ejemplo: Heap, Stack, LibC, etc. Impide ataques que utilizan direcciones “hardcodeadas”(como los vistos hoy)No todo se “randomiza”. Por lo general, la sección de texto de un programa no lo cambia. Para que lo haga, se tiene que compilar especialmente para ser Position Independent Code.Si está compilado con PIE el sistema operativo puede cambiar su dirección base entre sucesivas ejecuciones.Al igual que DEP, también es “bypasseable” (aunque puede ser más difıcil)

58
Q

Explicar SETUID. Explicar otro método (distinto a setuid y setguid) para ejecutar con permisos de otro usuario.

A

Cuando un proceso ejecuta un comando exec en un archivo con el bit SETUID o SETGID activado, adquiere un nuevo UID o GID efectivo. Con una combinación diferente de (UID, GID), tiene un conjunto diferente de archivos y operaciones disponibles. Ejecutar un programa con SETUID o SETGID también es un cambio de dominio, ya que cambian los derechos disponibles.

Los archivos ubicados en directorios de usuarios, pero que son propiedad del superusuario y tienen el bit SETUID activado, son potenciales problemas de seguridad porque tales archivos adquieren los poderes del superusuario cuando son ejecutados por cualquier usuario.

59
Q

¿Para qué sirve el bit NX (No eXecute) de la tabla de páginas?

A

The NX bit (no-execute) is a technology used in CPUs to segregate areas of a virtual address space to store either data or processor instructions. An operating system with support for the NX bit may mark certain areas of an address space as non-executable. The processor will then refuse to execute any code residing in these areas of the address space. The general technique, known as executable space protection, also called Write XOR Execute, is used to prevent certain types of malicious software from taking over computers by inserting their code into another program’s data storage area and running their own code from within this section; one class of such attacks is known as the buffer overflow attack.

60
Q

Explicar buffer overflow y mecanismos para prevenirlo. (canario, páginas no ejecutables, randomización de direcciones) ¿En qué parte de la memoria se buscan hacer los buffer overflow? (En el stack, pero también se puede hacer en el heap.

A

buffer overflow es un error de software que se produce cuando un programa no controla adecuadamente la cantidad de datos que se copian sobre un área de memoria reservada a tal efecto (buffer): Si dicha cantidad es superior a la capacidad preasignada, los bytes sobrantes se almacenan en zonas de memoria adyacentes, sobrescribiendo su contenido original, que probablemente pertenecían a datos o código almacenados en memoria.
La capacidad de los procesadores modernos para marcar zonas de memoria como protegidas puede usarse para aminorar el problema. Si se produce un intento de escritura en una zona de memoria protegida se genera una excepción del sistema de acceso a memoria (segfault), seguido de la terminación del programa. Por desgracia para que esta técnica sea efectiva los programadores han de indicar al sistema operativo las zonas que se necesita proteger, programa a programa y rutina a rutina, lo que supone un problema para todo el código heredado. ‘
Stack Canaries:

Una defensa comúnmente utilizada contra el ataque esbozado anteriormente es el uso de canarios de pila. Los sistemas informáticos modernos todavía usan canarios (digitales) como sistemas de alerta temprana. La idea es muy simple. En los lugares donde el programa realiza una llamada a una función, el compilador inserta código para guardar un valor de canario aleatorio en la pila, justo debajo de la dirección de retorno. Al retornar de la función, el compilador inserta código para verificar el valor del canario. Si el valor cambió, algo está mal. En ese caso, es mejor presionar el botón de pánico y bloquearse en lugar de continuar.

Prevención de Ejecución de Datos:

Las CPUs modernas tienen una característica que se conoce popularmente como el bit NX, que significa “No-eXecute” (No ejecutar). Es extremadamente útil para distinguir entre segmentos de datos (montón, pila y variables globales) y el segmento de texto (que contiene el código). Específicamente, muchos sistemas operativos modernos intentan asegurar que los segmentos de datos sean escribibles, pero no ejecutables, y que el segmento de texto sea ejecutable, pero no escribible. Esta política se conoce en OpenBSD como WˆX (pronunciado como “W Exclusive-OR X” o “W XOR X”). Significa que la memoria es o escribible o ejecutable, pero no ambas cosas. Mac OS X, Linux y Windows tienen esquemas de protección similares. Un nombre genérico para esta medida de seguridad es DEP (Prevención de Ejecución de Datos). Algunos hardware no soportan el bit NX. En ese caso, DEP todavía funciona, pero la aplicación se realiza en software. DEP previene todos los ataques discutidos hasta ahora. El atacante puede inyectar tanto shellcode en el proceso como quiera. A menos que pueda hacer que la memoria sea ejecutable, no hay manera de ejecutarlo.

Aleatorización de Disposición del Espacio de Direcciones:

Aquí hay otra idea para detener estos ataques. Además de modificar la dirección de retorno e inyectar algún programa (ROP), el atacante debe ser capaz de retornar a la dirección correcta exacta; con ROP no se pueden usar nop sleds. Esto es fácil si las direcciones son fijas, pero ¿qué pasa si no lo son? ASLR (Aleatorización de Disposición del Espacio de Direcciones) tiene como objetivo aleatorizar las direcciones de funciones y datos entre cada ejecución del programa. Como resultado, se vuelve mucho más difícil para el atacante explotar el sistema. Específicamente, ASLR a menudo aleatoriza las posiciones de la pila inicial, el montón y las bibliotecas. Al igual que los canarios y DEP, muchos sistemas operativos modernos soportan ASLR, pero a menudo con diferentes granularidades. La mayoría de ellos lo proporcionan para aplicaciones de usuario, pero solo unos pocos lo aplican consistentemente también al núcleo del sistema operativo (Giuffrida et al., 2012). La fuerza combinada de estos tres mecanismos de protección ha elevado significativamente el nivel para los atacantes. Simplemente saltar a código inyectado o incluso a alguna función existente en la memoria se ha vuelto un trabajo arduo. Juntos, forman una línea de defensa importante en los sistemas operativos modernos. Lo que es especialmente bueno acerca de ellos es que ofrecen su protección a un costo muy razonable para el rendimiento.

61
Q

¿Cómo se genera el canario? ¿En tiempo de compilación o de ejecución?

A

Implementado a nivel del compilador
Se coloca un valor en la pila luego de crear el stack frame
Antes de retornar de la función se verifica que el valor sea el correcto.
La idea es proteger el valor de retorno de la funci´on de posibles buffer overflows
Esta técnica, también es “bypasseable”.
Los canarios de pila o cookies de seguridad son valores indicativos que se agregan a los binarios durante la compilación para proteger valores críticos de la pila, como el puntero de retorno, contra ataques de desbordamiento de búfer. Si se detecta un canario incorrecto durante ciertas etapas del flujo de ejecución, como justo antes de un retorno (RET), el programa se terminará.

62
Q

Explicar el ataque Return to libc.

A

Supongamos que el desbordamiento de búfer de la Fig. 9-22 ha sobrescrito la dirección de retorno de la función actual, pero no puede ejecutar código suministrado por el atacante en la pila. La pregunta es: ¿puede retornar a otro lugar? Resulta que sí puede. Casi todos los programas en C están vinculados con la biblioteca (generalmente compartida) libc, que contiene funciones clave que la mayoría de los programas en C necesitan. Una de estas funciones es system, que toma una cadena como argumento y la pasa al shell para su ejecución. Así, usando la función system, un atacante puede ejecutar cualquier programa que desee. Entonces, en lugar de ejecutar shellcode, el atacante simplemente coloca una cadena que contiene el comando a ejecutar en la pila, y desvía el control a la función system a través de la dirección de retorno. El ataque se conoce como return to libc y tiene varias variantes. System no es la única función que puede ser interesante para el atacante. Por ejemplo, los atacantes también pueden usar la función mprotect para hacer ejecutable parte del segmento de datos. Además, en lugar de saltar directamente a la función libc, el ataque puede tomar un nivel de indirecta.

63
Q

Dar un ejemplo de un error de seguridad ocasionado por race condition. (cambiar concurrentemente puntero de symbolic links)

A

Un race condition (condición de carrera) ocurre cuando el comportamiento de un sistema depende del orden o del momento de ejecución de procesos o threads, y ese orden no se controla explícitamente. En el contexto de sistemas de archivos, un ataque de race condition puede explotarse para comprometer la seguridad, especialmente cuando se manipulan symbolic links (enlaces simbólicos).

  1. Programación del Cambio de Propietario (chown) en un Symbolic Link:
    • Un administrador desea cambiar el propietario de un archivo sensible. El administrador ejecuta un comando para cambiar el propietario del archivo:
      sh
      chown usuario_nuevo /ruta/al/archivo
  2. Ataque Race Condition con Symbolic Link:
    • Un atacante con acceso a la misma máquina puede aprovechar el intervalo de tiempo entre la verificación del archivo objetivo y la aplicación del comando chown.
    • El atacante crea un enlace simbólico (symlink) en un directorio temporal:
      sh
      ln -s /ruta/al/archivo /tmp/symlink
  3. Cambio Concurrente del Symbolic Link:
    • El atacante ejecuta un script que cambia el enlace simbólico para que apunte a otro archivo de manera repetida, intentando sincronizar con la ejecución del comando chown del administrador:
      sh
      while true; do
          ln -sf /otro/archivo /tmp/symlink
          ln -sf /ruta/al/archivo /tmp/symlink
      done
  4. Ejecución del Comando chown:
    • El administrador, sin sospechar, ejecuta:
      sh
      chown usuario_nuevo /tmp/symlink
    • Si el comando chown se ejecuta mientras el symbolic link apunta a /otro/archivo, el propietario de /otro/archivo cambiará a usuario_nuevo, comprometiendo así la seguridad del archivo original.
  • Escalada de Privilegios:
    • Si el archivo objetivo que el atacante logra apuntar al symbolic link tiene permisos de acceso restringidos, el atacante podría obtener acceso a recursos sensibles al cambiar sus permisos o propietario.
  • Integridad de Datos:
    • El atacante podría alterar archivos críticos del sistema o archivos de otros usuarios, afectando la integridad del sistema.
  • Acceso No Autorizado:
    • Manipular permisos o propietarios de archivos puede permitir al atacante acceder a archivos que normalmente estarían fuera de su alcance.
  1. Uso de O_NOFOLLOW y O_EXCL:
    • Al abrir archivos, usar flags que prevengan el seguimiento de enlaces simbólicos.
      c
      int fd = open("/ruta/al/archivo", O_WRONLY | O_NOFOLLOW);
  2. Verificación Atómica:
    • Asegurarse de que las verificaciones y operaciones sobre archivos sean atómicas.
  3. Uso de Funciones Seguras:
    • Utilizar funciones específicas para tratar con enlaces simbólicos de manera segura, como lchown en lugar de chown, para operar directamente sobre el enlace simbólico y no sobre el archivo al que apunta.
      sh
      lchown /tmp/symlink usuario_nuevo

El ejemplo descrito ilustra cómo un race condition puede ser explotado utilizando symbolic links para comprometer la seguridad del sistema. La prevención de tales vulnerabilidades implica el uso de prácticas de programación seguras, como el uso de flags adecuados y funciones atómicas, para mitigar los riesgos asociados con las condiciones de carrera.

64
Q

Explicar las diferencias entre MAC y DAC.

A

La diferencia entre DAC (Discretionary Access Control) y MAC (Mandatory Access Control) es que en el primero el dueño del archivo puede especificar quiénes tienen acceso, mientras que en el segundo esto se configura automáticamente en función del nivel de prioridad que tiene el último usuario que lo modificó.

65
Q

¿Qué es una firma digital? Explicar cómo es el mecanismo de autenticación.

A

Firma digital: calculó un hash del documento.
Encripto con mi clave privada el hash.
Entrego el documento + el hash encriptado.
El receptor lo desencripta con mi clave pública. Si lo puede desencriptar exitosamente se asegura de que yo sea el autor.
Luego verifica que el hash así obtenido se corresponda con el documento.
Además de la cuestión técnica, no hay que descuidar el marco legal que le da validez (Ley 25.506)
Si solo se pretende tener certeza sobre el origen de un mensaje, una solución simple consiste en encriptarlo con la clave privada y que el receptor lo desencripte con la clave pública. De este modo se asegura de que la fuente del mensaje es quien esperaba que sea. Cabe notar que este método no provee confidencialidad sobre los contenidos del mensaje, ya que cualquiera tiene la clave pública, solo tiene que saber quién mandó ese mensaje
Ahora bien, como encriptar con la clave privada es computacionalmente caro para mensajes largos, se ideó otro mecanismo, que tampoco provee confidencialidad sobre el mensaje pero es mucho más barato. Éste consiste en utilizar una función de hash sobre el mensaje, que genera un “resumen” del mismo de tamaño fijo, sin importar el tamaño original del mensaje. Dicha función de hash debe complir con ciertas propiedades, como que sea computacionalmente inviable hallar la preimagen de un resumen y que sea computacionalmente inviable hallar dos mensajes que tengan el mismo resumen. El resumen es firmado (encriptado con la clave privada) y enviado al destinatario junto con el mensaje original. El receptor toma el mensaje y lo hashea, toma el resumen firmado y lo desencripta, si el resumen desencriptado y el resultado de hashear el mensaje son iguales entonces queda asegurado que el origen era el esperado y que la integridad del mensaje es total.

66
Q

¿Qué es una función de hash? ¿Cómo se usa en el log-in de un SO? ¿Qué problemas tiene usar un hash para autenticar usuarios? ¿Cómo se puede mejorar la seguridad? ¿Qué es un SALT? ¿Cómo podemos hacer que calcular la función de hash sea más costoso? ¿Qué otros usos tiene la función de hash en seguridad?

A

Una función hash H(m) crea un pequeño bloque de datos de tamaño fijo, conocido como digest del mensaje o valor hash, a partir de un mensaje m. Las funciones hash funcionan tomando un mensaje, dividiéndolo en bloques y procesando los bloques para producir un hash de n bits. H debe ser resistente a colisiones, es decir, debe ser inviable encontrar un m′ ≠ m tal que H(m) = H(m′). Ahora, si H(m) = H(m′), sabemos que m = m′, es decir, sabemos que el mensaje no ha sido modificado. Las funciones de digest de mensajes comunes incluyen MD5 (ahora considerado inseguro), que produce un hash de 128 bits, y SHA-1, que genera un hash de 160 bits. Los digest de mensajes son útiles para detectar cambios en los mensajes, pero no son útiles como autenticadores. Por ejemplo, H(m) puede ser enviado junto con un mensaje; pero si H es conocido, entonces alguien podría modificar m a m′ y recomputar H(m′), y la modificación del mensaje no sería detectada. Por lo tanto, debemos autenticar H(m).
Se usa el para el login porque basta comparar el has guardado con el que mandan y si son los hash son iguales los parámetros deben ser iguales.
Funciones de hash: Se usan para almacenar contraseñas que no se puedan leer. También sirve para enviar esas contraseñas a través de un sistema.
Se suele pedir que cumplan con:
Resistencia a la preimagen. Dado h debería ser difícil encontrar un m tal que h =hash(m). (No inversible)
Resistencia a la segunda preimagen. Dado m1 debería ser difícil encontrar un m2 != m1 tal que hash(m1)=hash(m2).
Funciones de hash one-way. MD5, SHA1, SHA-256, et.
Ahora esto se puede vulnerar si se usa un diccionario de contraseñas y se tiene acceso a la función de hash. Pues podes ver si encontras una contraseña que matchee con el hash que interceptaste.
SALT: Se usa una función de hash doble con un valor de semilla como 2do parametro. O también se puede agregar al final de la clave un valor random. Esto hace más dificil usar la estrategia anterior. Además te salva en el caso de que dos usuarios usen la misma contraseña. Además si te vulneran una contraseña solo acceden a la de un usuario de los que comparte contraseña.
Su idea es asociar un número aleatorio de n bits, llamado “salt”, con cada contraseña. El número aleatorio se cambia cada vez que se cambia la contraseña. El número aleatorio se almacena en el archivo de contraseñas en forma no cifrada, para que cualquiera pueda leerlo. En lugar de simplemente almacenar la contraseña cifrada en el archivo de contraseñas, la contraseña y el número aleatorio se concatenan primero y luego se cifran juntos

67
Q

¿Qué es una clave pública/privada? ¿Cómo podemos distribuir una clave pública?

A

Método RSA:
Tomamos dos números muy grandes. Uno será la clave pública(difunde) y el otro la clave privada(desencripta los mensajes y debe resguardar).
Encriptar: tomo cada char del mensaje como un int y hago una cuenta de módulo usando la clave pública del receptor.
Desencriptar: Tomo cada número y resuelvo una congruencia usando mi clave privada. Con el resultado construyo el mensaje y lo paso a chars.
En detalle la generación de claves:
Tomo p, q primos de +200 digitos ⇒ n = pq y n’ = (p-1)(q-1)
Tomo un e q esté entre 2 y n’-1 y sea coprimo con n’.
Calculo d / d*e ☰ 1 (n’)
clave pública = (e, n) clave privada = (d, e)
En detalle como encriptar y desencriptar:
Encripto? Calculo x cada letra c ☰ m^e (n)

68
Q

¿Por qué es más seguro utilizar un esquema de clave pública/privada para una conexión por ssh, comparado con usuario/contraseña?

A

porque la claves privada está guardado en el usuario en vez de tener el usuario y contraseña en el server que lo hace más vulnerable(cuestionable)

69
Q

¿Se puede considerar Deadlock un problema de seguridad?

A

Si, con el ataque de “denegación de servicios” (DoS) te pueden atacar por ese lado.
Es decir, si algún atacante conoce una manera en la cual puede producir un deadlock en un sistema, al producirlo estaría “trabando” varias partes del sistema y dejando fuera de correcta ejecución las mismas, y esto puede verse como que el sistema está negado de servicios.

70
Q

¿Qué problemas de seguridad hay asociados a los file descriptors? ¿Cómo lo resuelve SELinux?

A

SI logran cambiar el file descriptor pueden leer o escribir de otro archivo.
SELinux proporciona el mecanismo para implementar una políticas de control de acceso de tipo Control de acceso obligatorio (MAC) y control de acceso basado en role.

71
Q

¿Qué es la virtualización y los contenedores? ¿Cómo se implementan?

A

Virtualización: es la posibilidad de que un conjunto de recursos físicos se vean como varias copias de recursos lógicos. La acepción más común es pensar en una computadora realizando el trabajo de varias.
Desde hace rato (por lo menos 1960) tener máquinas virtuales. Ie, de mentira. Los objetivos son variados:
Portabilidad (Java Virtual Machine).
Simulación/testing.
Aislamiento (como chroot, jail y cía).
Particionamiento de HW.
Agrupamiento de funciones (“consolidation”).
Protección ante fallas de HW (migración de HW).
Migración entre HW sin pérdida de servicio.

Concepto de VMM/Hypervisor: es un software/firmware/hardware específico destinado a crear, correr y administrar máquinas virtuales.
Tipo 0 (Hardware / Firmware): Es un tipo especial de virtualización, en donde el propio hardware se encarga de la virtualización, generando “particiones” o
“dominios” de ejecución. Cualquier Sistema Operativo que corra en un dominio, ve el hardware como si fuera exclusivo, no sabe que en realidad posiblemente está siendo compartido con otros Sistemas Operativos en otros dominios.
Funciona de forma “transparente”. La administración de IO puede generar problemas.
Tipo 1 (Nativo / Unhosted / Bare Metal): Se ejecuta directamente sobre el hardware. Si bien se ejecuta directamente sobre el hardware, el VMM en sí es un Sistema Operativo, que provee funciones mínimas e indispensables (CPU scheduling, administración de IO, protección y seguridad). Muchas veces se provee, además, una API de administración (local, remota).
Ejemplos: VMware ESXi, XEN, Citrix XenServer, Microsoft Hyper-V Server,
Oracle VM.
Tipo 2 (Hosteado): Se ejecuta como un software más. Técnicamente, puede correr sobre cualquier Sistema Operativo, sin requerir de un soporte especial.
Por lo general la mayoría de las opciones requieren privilegios de Kernel, y para
ello usan módulos específicos en el sistema operativo Host. Todo esto obviamente agrega un overhead a la virtualización. Ejemplos: Virtualbox, VMware Workstation/Server/Player, QEMU, Virtual PC.
Paravirtualización: No es exactamente virtualización. Requiere de un host y un guest modificados especialmente para funcionar. Traduce las llamadas al sistema operativo guest en llamadas al sistema operativo host, por lo que estas corren localmente en el host. El sistema operativo guest tiene que estar adaptado para utilizar la para-API provista por el VMM, por lo que un sistema operativo convencional (sin modificar) no puede correr sobre un VMM con paravirtualización.Esta técnica tiene muchas ventajas en cuanto a performance.
Caso típico: Xen
Virtualización del Entorno de Programación: es virtualización basada en un modelo de ejecución distinto al típico, en donde lo que se virtualiza es el entorno de ejecución. Requiere contar con un soporte de Lenguaje/Software. Caso típico: JVM

Carácterísticas esenciales de los VMM (Popek y Goldberg, 1974) :
Fidelidad Performance Safety
Fidelidad (equivalence): Un programa corriendo en una VMM debe exhibir un comportamiento esencialmente idéntico al que tendría si estuviese corriendo en una máquina física.
Performance (efficiency): Una porción estadísticamente significativa de las instrucciones de máquina deben ser ejecutadas sin la intervención del VMM (es decir, para que no sea emulación).
Control de Recursos (safety): El VMM debe estar en completo control de los recursos virtualizados.
Contenedores: Nos crear un enviroment adecuado para correr alguna aplicación específica. Encapsular un único paquete ejecutables con el el código de la aplicación, los archivos de configuración, librerías y dependencias necesarias para que pueda correr. Esto es clave si estamos desarrollando en un equipo que tiene un ambiente distinto al que usará nuestra app. Son una forma de virtualizar un SO. Como no contienen la imágen del SO son mucho más ligeros que las VM.

72
Q

¿Qué es un proceso cooperante?

A

Un proceso cooperante es aquel que puede afectar o ser afectado por otros procesos que se ejecutan en el sistema. Los procesos cooperantes pueden compartir directamente un espacio de direcciones lógico (es decir, tanto el código como los datos) o compartir datos solo a través de memoria compartida o paso de mensajes. El acceso concurrente a datos compartidos puede resultar en inconsistencia de datos, por eso necesitamos sincronización.