viernes, 5 de marzo de 2010

fork y clone

fork()

La llamada fork() se utiliza para crear un nuevo proceso. Su estructura es:

pid_t fork(void);

fork hace que el sistema cree un nuevo proceso hijo, con un nuevo PID. Tras ejecutarse el proceso hijo, devuelve el control al proceso padre, y este se ejecuta.

El valor de retorno (pid_t) se usa para identificar al proceso. Regresa 0 cuando se trata del proceso hijo, -1 si hubo algún error y cualquier otro valor para el proceso padre.

Suele utilizarse de la siguiente manera (ejemplo):

pid_t pid;

....

pid=fork();

if (pid==-1) {

perror("Error");exit(-1)}

if (pid==0)

{.... código del proceso hijo ....}

else

{.... código del proceso padre ....}

En el ejemplo se declara una variable pid_t, para obtener el identificador del proceso. Cuando se crea el proceso con fork, pid tendrá el valor de 0, por lo que se ejecutará el código del proceso hijo. Cuando devuelva el control al proceso padre, éste hará que pid tenga un valor distinto a 0 (más específicamente, el pid del proceso hijo), por lo que se ejecutará el código del proceso padre.

Fork es usado cuando desea duplicarse un proceso o ejecutar un programa independiente, ya que hace una copia de memoria, heap y stack del padre.

Referencias:

  • · http://www.arrakis.es/~ofafian/unix-lec2.html
  • · http://profesores.elo.utfsm.cl/~agv/elo330/2s09/lectures/ControlProcesos.html
  • · Páginas 16, 17 y 18 del manual “Llamadas al Sistema de DSC”





clone()

La función clone realiza una tarea similar a fork, crear procesos hijos al proceso que lo ejecuta. A diferencia del fork, clone permite que el proceso hijo comparta partes de su contexto de ejecución con el proceso padre, como el espacio de memoria, la tabla de descriptores de fichero y la tabla de manejadores de señales (signal handler). El uso que habitualmente se le da a clone es para implementar hilos de ejecución (threads): múltiples hilos de ejecución de control en un programa que corre en un espacio de memoria compartido. Se implementa del siguiente modo:

int clone (int (*fn) (void *), void *child_stack, int flags, void *arg);


Cuando se crea un proceso hijo con clone se ejecuta la función fn(arg). El argumento fn es un puntero a una función. El entero que debe retornar esa función será el código de salida del proceso hijo. El proceso hijo podría también finalizar explícitamente mediante una llamada a exit o después de recibir una señal fatal.

El argumento child_stack especifica la posición de la pila usada por el proceso hijo. Ya que el proceso hijo y el padre pueden compartir la misma memoria, no es posible que el proceso hijo ejecute la misma pila que el proceso padre. El proceso padre (el que invoca la función clone) prepara un espacio de memoria para la pila del hijo y le pasa un puntero a este espacio mediante este argumento.

El argumento entero flag es un OR de varias constantes que especifican que es compartido entre padre e hijo:

CLONE_PARENT, CLONE_FS, CLONE_FILES, CLONE_NEWSNS, CLONE_SIGHAND, CLONE_PTRACE, CLONE_UNTRACED, CLONE_STOPPED, CLONE_VFORK, CLONE_VM, CLONE_PID, CLONE_THREAD, CLONE_SYSVEM, CLONE_SETTLS, CLONE_PARENT_SETTID, CLONE_CHILD_SETTID, CLONE_CHILD_CLEARID

La función clone retorna el TID (Thread ID, identificador del hilo) o -1 en caso de fallo y errno será asignado apropiadamente describiendo el error.

Ejemplo:

int cloneando()
{
        printf("Hola mundo clonado\n");
}

int main(int argc,char** argv)
{
        void **pila_hijo;
        pila_hijo = malloc(1000);
        clone(cloneando,pila_hijo, CLONE_VM|CLONE_FILES, NULL);
        sleep(1);
        printf("Hola mundo real\n");
        return 0;
}

Referencias:

  • · http://sopa.dis.ulpgc.es/ii-dso/leclinux/procesos/fork/LEC7_FORK.pdf
  • · http://www.novanebula.net/blog/archives/69-Clone-en-Linux.html





Þø® €vîlwîzå®dîngtøn

No hay comentarios:

Publicar un comentario