Esta página puede ser redistribuida libremente bajo los términos de la licencia GPL. Vease ( GPL texto original ) o si lo prefiere (Traducción española no oficial de la GPL) Al margen de las obligaciones legales que se derivan del uso de esta licencia rogamos sea respetada la referencia a su lugar de publicación original www.ciberdroide.com. y a su autor original Antonio Castro Snurmacher (Madrid 01/01/2000).

Ausencia de Garantía

Esta ausencia de garantía se hace extensa a cualquier tipo de uso de este material y muy especialmente a las prácticas, ejercicios, y de ejemplos que encuentre en estas páginas. Deberá trabajar siempre salvo indicación contraria con un SO Linux y con un usario distinto de 'root' sin privilegios especiales. Como directorio de trabajo se procurará usar el directorio '/tmp' o algún otro que no contenga información valiosa. Tampoco se considera buena idea practicar en una máquina que contenga información valiosa.

Todo esto son recomendaciones de prudencia. En cualquier caso si algo sale mal toda la responsabilidad será únicamente suya. En ningún caso podrá reclamar a nadie por daños y perjuicios derivados del uso de este material. Para más información lea el contenido de la licencia GPL y abstengase de hacer prácticas si no está dispuesto a asumir toda la responsabilidad.

...
..

INTRODUCCION A LOS PROCESOS

Que es un proceso
A estas alturas más de uno empezará a preguntarse si realmente es necesario conocer todos estos detalles para un simple uso de un SO. Este curso esta orientado al uso de Linux desde la consola y resulta necesario conocer estas cosas incluso para un usuario normalito. No vamos a describir detalladamente como están implementados los procesos en Linux.

Quizas para un curso de programación avanzada si fuera necesario, pero lo que nosotros vamos a describir es unicamente los detalles más importantes desde un punto de vista didáctico y práctico para un usuario normal.

En un sistema multitarea todo funciona con procesos así que conocer unos cuantos principios básicos sobre procesos le resultará de la máxima utilidad. En un sistema monotarea se usa frecuentemente el término programa indistintamente para hablar de un programa en papel, en cdrom, en disco duro o en funcionamiento. En un sistema multitarea no se debe usar el término programa para hablar de la ejecución del mismo. En su lugar hablaremos de proceso indicando con ello que esta arrancado y funcionando. Un programa puede dar lugar a varios procesos. Por ejemplo en un mismo instante varios usuarios pueden estar usando un mismo editor. Un proceso puede estar detenido pero a diferencia de un programa existe una informacíon de estado asociada al proceso. Un programa es algo totalmente muerto. Un proceso detenido es más bien como si estuviera dormido.

Los procesos tienen organizada la memoria de una forma especial muy eficiente. Por ejemplo la párte de código del proceso es una parte de solo lectura y puede ser compartida por varios procesos a la vez. Imaginemos que hay varios usuarios en el sistema usando un mismo editor. En ese caso sería un desperdicio tenener la mísma información de código de ese programa repetida varias veces en memoria y ocupando un recurso tan valioso como es la memoria RAM.

En el caso de tener varios programas distintos en ejecución también se suele dar el caso de que contengan pártes comunes de código pertenecientes a librerías que continen gran cantidad de funciones de propósito general. Para hacer un uso eficiente de estas librerías existen librerías dinámicas de uso compartido. En Linux el uso de estas librerías no está organizado de una forma unificada para todas las distribuciones por lo cual los ejecutables binarios pueden ser incompatibles entre distintas distribuciones. Este problema se puede solucionar partiendo de los fuentes y recompilando la aplicación en nuestro sistema. Por esta razón un binario de RedHat, o Suse puede no funcionar en Slackware o en Debian.

PID y PPID
A cada proceso le corresponderá un número PID que le identifica totalmente. Es decir en un mismo momento es imposible que existan dos procesos con el mismo PID. Lo mismo que todos los procesos tienen un atributo PID que es el número de proceso que lo identifica en el sistema tambien existe un atributo llamado PPID. Este número se corresponde con el número PID del proceso padre. Todos los procesos deben de tener un proceso que figure como padre pero entonces que ocurre si un padre muere antes que alguno de sus hijos ? En estos casos el proceso 'init' del cual hablaremos en seguida adoptará a estos procesos para que no queden huerfanos.

El proceso init
Cuando arranca el sistema se desencadena una secuencia de procesos que a grandes rasgos es la siguiente. Primero se carga el nucleo de Linux (Kernel) de una forma totalmente especial y distinta a otros procesos. Dependiendo de los sitemas puede existir un proceso con PID=0 planificador, o swapper. En Linux y en casi todos los sistemas tipo Unix seguirá un proceso llamado 'init'. El proceso init tiene PID = 1. Lee un fichero llamado inittab donde se relacionan una serie de procesos que deben arrancarse para permanecer activos todo el rato (demonios). Algunos de ellos están definidos para que en caso de morir sean arrancados de nuevo inmediatamente garantizando la existencia de ese servicio de forma permanente.

Es decir 'init' es un proceso que va a generar nuevos procesos pero esta no es una cualidad especial. Es muy frecuente que un proceso cualquiera genere nuevos procesos y cuando esto ocurre se dice que genera procesos hijos.

Este no es un curso de administración pero diremos que a init se le puede indicar que arranque el sistema de diferentes formas, por ejemplo en modo monousuario para mantenimiento. Este es un capítulo en el cual pueden surgir muchas preguntas retorcidas tales como, que pasa si matamos a init, o quien es el padre de init, pero no nos interesa responder a esto ya que init es un proceso muy especial y su padre aún más. En cada sistema de tipo Unix las respuestas a cosas como estas pueden variar mucho porque a ese nivel la implementaciones varían mucho. Ningún programa normal necesitará usar ese tipo de información. Quedan muchos detalles interesantes relativos a temas de administración. Los curiosos siempre tienen el recurso de mirar la página man de init(8) y de inittab(5) pero nosotros no insistiremos más en este tema. (Que alivio verdad ?)

UID y EUID
Los procesos tienen un EUID (Efectiv User Identif), y un UID normalmente ambos coinciden. El UID es el identificador de usuario real que coincide con el identificador del usuario que arrancó el proceso. El EUID es el identificador de usuario efectivo y se llama así porque es el identinficador que se tiene en cuenta a la hora de considerar los permisos que luego explicaremos.

El UID es uno de los atributos de un proceso que indica por decirlo de alguna manera quien es el propietario actual de ese proceso y en función de ello podrá hacer ciertas cosas. Por ejemplo si un usuario normal intentara eliminar un proceso del cual no es propietario el sistema no lo permitirá mostrando un mensaje de error en el que advierta que usted no es el propietario de ese proceso y por tanto no está autorizado a hacer esa operación. Por el contrario el usuario root puede hacer lo que quiera con cualquier proceso ya que el sistema no comprueba jamás si root tiene permisos o no para hacer algo. root siempre tiene permisos para todo. Esto es cierto a nivel de llamadas del sistema pero nada impide implementar un comando que haga comprobaciones de permisos incluso con root. Algunos comandos en Linux tienen opciones que permiten hacer estas cosas y solicitar confirmación en caso de detectar una operación peligrosa o infrecuente.

El UID también es un atributo presente en otros elementos del sistema. Por ejemplo los ficheros y directorios del sistema tienen este atributo. De esta forma cuando un proceso intenta efectuar una operación sobre un fichero. El kernel comprobará si el EUID del proceso coincide con el UID del fichero. Por ejemplo si se establece que determinado fichero solo puede ser leido por su propietario el kernel denegará todo intento de lectura a un proceso que no tenga un EUID igual al UID del fichero salvo que se trate del todo poderoso root.

Aunque estamos adelantando cosas sobre el sistema de ficheros vamos a continuar con un ejemplo. Comprobaremos cual es el UID de su directorio home.

# Cambiamos el directorio actual a home
$ cd
# Comprobamos a quien pertenece 'uid' y 'guid'
$ ls -ld .
# Ahora obtenemos el 'uid' y el 'gid' con sus valores numéricos.
$ ls -lnd .

Si su directorio home está configurado de forma lógica deberá pertenecerle a usted. Si esto no es así reclame enérgicamente a su administrador, pero si el administrador resulta ser usted sea más indulgente y limitese a corregirlo y no confiese su error a nadie. En realidad casi todo lo que que se encuentre dentro de su directorio home debería pertenecerle a usted. Usted debe ser el propietario de su directorio home porque de otra forma y dependiendo de los permisos asociados a este directorio los procesos que usted arranque se verían o bien incapaces de trabajar con él, o lo que es peor cualquiera podría hacer cualquier cosa con él. Como es lógico hemos mencionado de pasada el tema de permisos de directorios para ilustrar un poco la utilidad del uid pero esto se verá en detalle en el capítulo dedicado al sistema de ficheros de Linux.

Algunos ficheros ejecutables poseen un bit de permisos que hace que cambie el EUID del proceso que lo ejecute convirtiendose en el UID del propietario del fichero ejecutado. Suena complicado pero no lo es. Es decir imaginemos que usted ejecuta un comando propiedad de root que tiene este bit. Pues bien en ese momento el EUID de su proceso pasaría a ser el de root. Gracias a esto un proceso puede tomar temporalmente la identidad de otro usuario. Por ejemplo puede tomar temporalmente la identidad de root para adquirir privilegios de superusuario y así acceder por ejemplo a ficheros del sistema propiedad de root.

El sistema recibe continuamente peticiones de los procesos y el EUID del proceso determinará que el kernel le conceda permiso para efectuar la operación deseada o no.

Muchas veces sorprende que en Linux apenas se conozcan unos pocos casos de virus, mientras que en otros sistemas parecen estar a la orden del día. Es perfectamente posible realizar un virus que infecte un sistema Linux pero de una forma o de otra el administrador tendría que darle los privilegios que le convierten en peligroso. Por eso no es facil que estos virus lleguen muy lejos.

Como se crea un nuevo proceso
El núcleo del sistema llamado también kernel es el encargado de realizar la mayoría de funciones básicas que gestiona entre otras cosas los procesos. La gestíon de estas cosas se hacen por medio de un limitado número de funciones que se denominan llamadas al sistema. Estas llamadas al sistema están implementadas en lenguaje C y hablaremos ahora un poco sobre un par de ellas llamadas fork() y exec(). Si logramos que tenga una vaga idea de como funcionan estas dos importantísimas funciones facilitaremos la compresión de muchas otras cosas más adelante.

La llamada al sistema exec()
Cuando hablamos de proceso debe usted pensar solamente en algo que se está ejecutando y que está vivo. Un proceso puede evolucionar y cambiar totalmente desde que arranca hasta que muere. Lo único que no cambia en un proceso desde que nace hasta que se muere es su identificador de proceso PID. Una de las cosas que puede hacer un proceso es cambiar por completo su código. Por ejemplo un proceso encargado de procesar la entrada y salida de un términal (getty) puede transformarse en un proceso de autentificacion de usuario y password (login) y este a su vez puede transformarse en un interprete de comandos (bash). Si la llamada exec() falla retornará un -1. Esto no es curso de programación así que nos da igual el valor retornado pero lo que si nos interesa es saber que cuando esta llamada tiene éxito no se produce jamás un retorno. En realidad no tendría sentido retornar a ningún lado. Cuando un proceso termina simplemente deja de existir. En una palabra muere y ya está. La llamada exec() mantiene el mismo PID y PPID pero transforma totalmente el código de un proceso en otro que cargará desde un archivo ejecutable.

La llamada al sistema fork()
La forma en que un proceso arranca a otro es mediante una llamada al sistema con la función fork(). Lo normal es que el proceso hijo ejecute luego una llamada al sistema exec(). fork() duplica un proceso generando dos procesos casi idénticos. En realidad solo se diferenciaran en los valores PID y PPID. Un proceso puede pasar al proceso hijo una serie de variables pero un hijo no puede pasar nada a su padre a través de variables. Además fork() retorna un valor numérico que será -1 en caso de fallo, pero si tiene éxito se habrá producido la duplicación de procesos y retornará un valor distinto para el proceso hijo que para el proceso padre. Al proceso hijo le retornará el valor 0 y al proceso padre le retornará el PID del proceso hijo. Después de hacer fork() se pueden hacer varias cosas pero lo primero que se utiliza despúes del fork es una pregunta sobre el valor retornado por fork() para así saber si ese proceso es el padre o el hijo ya que cada uno de ellos normalmente deberá hacer cosas distintas. Es decir la pregunta sería del tipo si soy el padre hago esto y si soy el hijo hago esto otro. Con frecuencia aunque no siempre el hijo hace un exec() para trasformarse completamente y con frecuencia aunque no siempre el padre decide esperar a que termine el hijo.

También normalmente aunque no siempre esta parte de la lección es necesario releerla más de una vez.

Estamos dando pequeños detalles de programación porque en estas dos llamadas del sistema son muy significativas. Su funcionamiento resulta chocante y su comprensión permite explicar un montón de cosas.

Test
Puede comprobar sus conocimientos respondiendo el siguiente test.
Para ello seleccione las opciones que se ajusten a la verdad y luego pulse el boton para ver el resultado de su test.

1 Un programa no puede generar un nuevo proceso si ya hay uno ejecutandose con el mismo programa.
2 No puede haber dos procesos con el mismo PPID.
3 El EUID es uno de los identificadores que usa el kernel para decidir sobre permisos.
4 Las llamadas al sistema son funciones que se ejecutan dentro del kernel.
5 Un proceso que hace 'exec' cambia su código por el contenido en un ejecutable.
6 Un proceso que hace 'fork' obtiene un nuevo proceso idéntico a si mismo salvo en su PID y su PPID.
7 La primera instrucción ejecutada por un proceso es la primera instrucción del código de su programa.

Resultado del test

Si quiere hacernos llegar alguna duda, aclaración,
crítica, o contribución personal, utilice nuestro
formulario de contacto y nosotros le contestaremos
contacto

.
....
...

Volver a la página anterior
Volver a la página principal de la tienda