FORK()

Crea un nuevo proceso, exactamente igual al proceso original, incluyendo los descriptores de ficheros, registros, ambiente, etc.

Una vez ejecutado el FORK, padre, e hijo se están ejecutando simultáneamente, en un principio las variables tienen los mismos valores, después, cambios en uno no afectan al otro.

La llamada FORK devuelve un valor después de ejecutarse, este valor es:

cero -> en el proceso hijo
pid (identificador del proceso hijo -> en el padre

Mediante este valor los procesos pueden saber cual es el padre y cual es el hijo.

wpe2.jpg (13876 bytes)

 

WAITPID

pid = waitpid(pid, &statloc, opts) - espera a que un hijo determinado termine, devolviendo el pid del proceso que termina, y coge su condición de salida.

En mucho casos, el hijo creado por el FORK necesita lanzar un proceso, distinto al del padre. Ejemplo:

El Shell, lee un comando, lanza un proceso hijo, y debe esperar hasta que el proceso hijo ejecute el comando, posteriormente lee un nuevo comando cuando el hijo termina.

Para esperar a que el hijo termine, el padre debe ejecutar WAITPID.

Si el parámetro pid vale -1, el padre espera por el primer hijo que termina

El segundo parámetro statloc es la dirección de una variable (estado de salida) que es escrita por el proceso hijo para indicar terminación normal o anormal.

 

EXEC.

s = execve (name, argv, envp) - sustituye la imagen en memoria de un proceso.

name - nombre del fichero que contiene el programa a ejecutar.

argv - vector de argumentos.

envp - vector ambiente

En el caso del Shell, el proceso hijo debe ejecutar el comando, esto lo hace mediante la llamada EXEC, la cual hace que la imagen del hijo, sea reemplazada por el fichero que hay en el primer parámetro de EXEC.

wpe3.jpg (30720 bytes)

Ejemplo: Shell simplificado con FORK, WAITPID y EXEC.

While (TRUE){ /* bucle indefinido */

read_command (command, parámetro); /* lee comando */

if(fork() != 0){ /* lanza un proceso hijo */

waitpid(-1,&status,0); /* el padre espera a que hijo acabe */

}else{

execve(command, parámetros, 0); /* ejecuta el comando */

}

}

Pregunta: ¿El Shell padre podría lanzar directamente el comando?

La respuesta es NO, ya que EXEC, reemplaza el fichero por el código de quien lo lanza, y este se pierde.

Muchas librerías, contienen varias versiones del EXEC.

execl, execv, execle, execve

que permiten omitir o especificar los parámetros de forma particular. Utilizaremos EXEC para referirnos a cualquiera de ellos.

Consideremos el ejemplo: cp file1 file2 copiar file1 en file2

Después que el Shell a creado con el FORK una imagen hijo, este hijo ejecuta cp mediante EXEC, le pasa al programa cp, y la información a cerca de los ficheros a copiarse.

El programa principal main de cp contiene los argumentos: main (argc, argv, envp)

argc -> Entero, contiene el número de parámetros (palabras) contenidos en la línea de comandos, en nuestro ejemplo 3.

argv -> Es un puntero a un vector, cada elemento del vector contiene un parámetro de la línea de comandos.

argv[0] = cp

argv[1] = file1

argv[2] = file2

envp -> Es un pointer o un vector ambiente, es un vector estring, conteniendo asignaciones de la forma (nombre = valor), utilizada para pasar información como el tipo del terminal, directorio, símbolo del Shell, etc.

 

EXIT().

Esta llamada la deben utilizar lo procesos cuando terminan.

Devuelve al padre un valor de estatus (0 a 255), que se carga en el byte menos significativo de la variable estatus de WAITPID, un cero es terminación normal, otro valor es error.

 

BRK(adr)

Esta llamada cambia el tamaño del segmento de datos de un programa.

El parámetro adr que indica el nuevo tamaño en bytes del segmento de datos. Devuelve el tamaño actual del segmento de datos.

La rutina sbrk, en la librería, también cambia el tamaño del segmento de datos, su parámetro indica el número de bytes que aumenta (positivo) o disminuye (negativo) el segmento de datos.

 

GETPID

Devuelve el identificador del proceso (pid) que lo ejecuta.

En un Fork, al padre se le devuelve el pid del hijo, mientras que al hijo se le devuelve un cero, si el hijo quiere saber su pid, deberá efectuar un GETPID.