CC31A

Control 2 - Semestre Primavera 2005

Viernes 30 de Septiembre de 2005

En sus respuestas sólo se le permite utilizar las llamadas a sistema de Unix y no las funciones de entrada/salida de alto nivel provistas por la biblioteca estándar de C (familia fopen/fread/fwrite/fclose y todas aquellas que involucren FILE * tanto explícita o implícitamente). Por su parte, puede definir todas las funciones, tipos y estructuras extra que necesite para la implementación de sus respuestas. Las consultas son en el puesto. Se permite el uso de apuntes impresos, fotocopiados, manuscritos, así como libros y computadores para efectos de documentación. Quienes usen computadores deben sentarse en la primera fila.

Pregunta 1: Comando tail

En Unix existe el comando tail, cuya forma de uso es:

% tail n
cuyo funcionamiento consiste en leer todo desde su entrada estándar e imprimir hacia su salida estándar las últimas n líneas de texto encontradas (incluyendo vacías). Se le pide que implemente este comando considerando que la cantidad total de líneas que vengan por la entrada estándar puede ser tan grande que no quepan todas simultáneamente en memoria.

Puede asumir que el parámetro n es siempre un número válido mayor o igual que 0 y que hay memoria para las n líneas, así como también que no se producen errores en las operaciones de entrada y salida. Puede usar malloc(). Por simplicidad, puede asumir que cada línea no tiene un largo mayor que LARGO_MAX (incluyendo '\n').

Pregunta 2: Manejo de señales

Se dispone del siguiente fragmento de código:

#define MAX_FD (40)
int fd_in;
int fds_out[MAX_FD];

#define MAX_BUF (4096)
char buff[MAX_BUF];
size_t llenado_buff;
size_t escrito_buff[MAX_FD];

void copiadora(void) {
  /* Función ya implementada */
}

void asegura_copia(void) {
  /* Función por implementar que llama a copiadora() */
}

int main() {
  /* Inicialización variables globales */
  asegura_copia();
}
donde la función copiadora lee reiteradamente desde el file descriptor fd_in hacia el buffer buff de tamaño MAX_BUF, dejando en llenado_buff lo que alcanzó a llenar del buffer, procediendo a continuación a copiar el contenido de buff hacia los MAX_FD file descriptors almacenados en fds_out y dejando en escrito_buff la cantidad de bytes de buff que ha alcanzado a escribir en cada uno de los file descriptor de salida. La escritura es realizada secuencialmente, un file descriptor tras otro, partiendo desde el primero. En main se inicializan todas las variables globales adecuadamente. Esta función ignora los file descriptors que valgan -1.

El problema es que este programa puede ser interrumpido por dos señales distintas:

Se le pide que implemente la función asegura_copia (así como otras funciones que necesite) de modo que maneje las señales mencionadas para que copiadora pueda seguir funcionando correctamente sin darse cuenta de qué ocurrió con las señales. El comportamiendo deseado es el siguiente:

Pregunta 3: fork y wait

Se necesita una función que indique si un número es o no primo utilizando varios procesadores para hacer cálculos parciales en procesos separados, sincronizando sus resultados en paralelo. Para ello, se le pide que implemente la siguiente función:

typedef unsigned long long int ullint_t;
int primo_par(ullint_t n, unsigned int n_procs);
la cual retorna verdadero o falso según si el número n es o no primo, respectivamente. Dicho cálculo debe hacerse usando n_procs procesos en paralelo. Por motivos de correctitud, una vez finalizada la función no debe haber procesos hijo en estado zombie.

Aquellas soluciones que no usen esta cantidad de procesos o no lo hagan en paralelo (en forma útil) no serán evaluadas. Puede asumir que n_procs es mayor que cero y que n es lo suficientemente grande como para que valga la pena usar todos los procesos pedidos. También puede asumir que todas las llamadas a fork() son exitosas y que todos los procesos terminan correctamente.

Hint: Para obtener la información de los procesos hijo puede usar la macro int WEXITSTATUS(int status), que obtiene el código de retorno del hijo a partir del estado obtenido por wait.