Sistemas operativos modernos
dado), pero no resulta atractivo tener que modificar el sistema operativo. Además, uno de los argumentos en favor de los subprocesos en el nivel de usuario era precisamente que pueden usarse con los sistemas operativos existentes. Otro problema es que alterar la semántica de read requeriría cambios en muchos programas de usuario. Hay otra alternativa en los casos en que es posible saber con antelación si se bloqueará o no una llamada. Algunas versiones de UNIX cuentan con una llamada al sistema, select, que indi ca al invocador si una llamada read propuesta se bloqueará o no. Si se dispone de esta llamada, el procedimiento de biblioteca read puede sustituirse por otro, que primero emite una llamada select y que sólo emite la llamada read si no hay peligro de que se bloquee. Si ésta va a blo quearse, no se emite. En vez de eso, se permite que otro subproceso se ejecute. La siguiente vez que el sistema de tiempo de ejecución obtenga el control, podrá verificar de nuevo si puede emi tir la llamada read sin peligro. Este enfoque requiere rescribir partes de la biblioteca de llama das al sistema, es poco eficiente y poco elegante, pero no hay más opciones. El código que se anexa a la llamada al sistema para efectuar la verificación se denomina funda o envoltura. Otro problema, hasta cierto punto análogo al de las llamadas bloqueadoras al sistema, es el de los fallos de página. Los estudiaremos en el capítulo 4, pero por ahora basta con decir que las computadoras pueden organizarse de manera tal, que no lodo el programa esté en la memo ria principal a la vez. Si el programa salta a una instrucción que no está en la memoria, ocurre un fallo de página y el sistema operativo trae la instrucción fallante (y sus vecinas) del disco. El proceso se bloquea mientras se localiza y lee la instrucción necesaria. Si un subproceso cau sa un fallo de página, el kemel, que ni siquiera sabe de la existencia de los subprocesos, blo queará todo el proceso hasta que termine la E/S de disco, aunque otros subprocesos puedan seguir ejecutándose. Otro problema de los sistemas de subprocesos en el nivel de usuario es que, si un subpro ceso comienza a ejecutarse, ningún otro subproceso de ese proceso se ejecutará si el primero no cede de manera voluntaria la CPU. Dentro de un proceso dado no hay interrupciones de re loj, así que es imposible la calendarización de subprocesos por tumo circular {round-robin). A menos que un subproceso ingrese en el sistema de tiempo de ejecución por voluntad propia, el calendarizador no tendrá oportunidad de trabajar. Una posible solución al problema de la ejecución indefinida de subprocesos es que el sistema de tiempo de ejecución solicite una señal de reloj (interrup>ción) una vez por segundo para asumir el control, pero esto también es burdo y molesto de programar. No siempre es posible emitir inte rrupciones de reloj periódicas con mayor fiwuencia y, aunque se pudiera, implicaría un procesa miento adicional considerable. Además, un subproceso también podría necesitar una intermpción de reloj, lo cual interferiría con el uso que hace del reloj el sistema de tiempo de ejecución. Otro argumento, tal vez el más devastador, en contra de los subprocesos en el nivel de usuario es que, en general, los programadores quieren subprocesos precisamente en las aplica ciones en las que éstos se bloquean a menudo, como en un servidor Web de múltiples subpro cesos. Estos subprocesos emiten llamadas al sistema en forma continua. Una vez que se ha entrado en el kemel para ejecutar la llamada al sistema, no representa mucho más trabajo para el kemel cambiar de subproceso si el último se bloqueó; por lo tanto, dejar que el kemel haga esto hace innecesario emifir llamadas select para ver si las llamadas read son seguras. En el caso de aplicaciones esencialmente dedicadas a la CPU, que pocas veces se bloquean, ¿qué ca-
RkJQdWJsaXNoZXIy MjI4NDcx