2011-03-11 15 views
13

Tengo un programa que usa fork() para crear un proceso secundario. He visto varios ejemplos que usan wait() para esperar a que el proceso hijo finalice antes del cierre, pero me pregunto qué puedo hacer para simplemente verificar si el proceso del archivo aún se está ejecutando.Comprobación del estado de un proceso secundario en C++

, básicamente, tienen un bucle infinito y quiero hacer algo como:

if(child process has ended) break;

¿Cómo podría ir haciendo esto?

Respuesta

33

Utilice waitpid() con la opción WNOHANG.

int status; 
pid_t result = waitpid(ChildPID, &status, WNOHANG); 
if (result == 0) { 
    // Child still alive 
} else if (result == -1) { 
    // Error 
} else { 
    // Child exited 
} 
+0

Así que la ChildPID es el que yo estoy usando para diferenciar entre padre e hijo y un nuevo resultado se pid_t que hace un nuevo sub-proceso que vela por el niño para salir? – Alex

+0

No, ChildPID es el ID del proceso del niño que '' regresó() tenedor. 'Waitpid()' es sólo una función que devuelve un valor: '0',' 'ChildPid' o -1' – Erik

+0

Bueno, lo que quiero decir es que hice un' 'pid_t' decir pid = tenedor()'. Ahora escribir código para mi padre y un hijo que tengo una 'pid' if-else que comprueba si' (PID) 'para identificar el proceso padre, porque en el proceso padre' pid' contiene el número pid del niño, y en el niño contiene '0'. Entonces, si estoy entendiendo esto correctamente, creo que debería usar 'pid', donde dijiste usar' ChildPID'. – Alex

1

No es necesario esperar a que un niño hasta que llegue la señal SIGCHLD. Si ha recibido esa señal, puede llamar al wait y ver si es el proceso secundario que está buscando. Si no ha recibido la señal, el niño todavía está corriendo.

Obviamente, si no tiene que hacer nada individualmente, el niño termina, simplemente llame al wait.

+3

¿Cómo sé si he recibido esa señal? – Alex

2

EDIT: Si solo quieres saber si el proceso hijo dejó de ejecutarse, entonces las otras respuestas son probablemente mejores. El mío tiene más que ver con la sincronización cuando un proceso puede hacer varios cálculos, sin necesariamente terminar.

Si tiene algún objeto que represente el cálculo secundario, agregue un método como bool isFinished() que devolverá verdadero si el elemento secundario ha finalizado. Tener un miembro bool privado en el objeto que representa si la operación ha finalizado. Finalmente, tenga otro método privado setFinished(bool) en el mismo objeto que su hijo procesa llamadas cuando termine su cálculo.

Ahora lo más importante es bloqueos mutex. Asegúrese de tener un mutex por objeto que bloquee cada vez que intente acceder a cualquier miembro, incluso dentro de los métodos bool isFinished() y setFinished(bool).

Edit2: (algunas aclaraciones OO)

Dado que se me pidió que explicar cómo esto podría hacerse con OO, voy a dar algunas sugerencias, aunque depende en gran medida el problema general, así que toma esto con un montón de sal. Tener la mayor parte del programa escrito en estilo C, con un objeto flotando alrededor es inconsistente.

Como un simple ejemplo, usted podría tener una clase llamada ChildComputation

class ChildComputation { 

    public: 
    //constructor 
    ChildComputation(/*some params to differentiate each child's computation*/) : 
     // populate internal members here { 
    } 
    ~ChildComputation(); 

    public: 
    bool isFinished() { 
     m_isFinished; // no need to lock mutex here, since we are not modifying data 
    } 

    void doComputation() { 
     // put code here for your child to execute 
     this->setFinished(true); 
    } 

    private: 
    void setFinished(bool finished) { 
     m_mutex.lock(); 
     m_isFinished = finished; 
     m_mutex.unlock(); 
    } 

    private: 
    // class members 
    mutex m_mutexLock; // replace mutex with whatever mutex you are working with 
    bool m_isFinished; 
    // other stuff needed for computation 
} 

En su programa principal, donde tenedor:

ChildComputation* myChild = new ChildComputation(/*params*/); 
ChildPID= fork(); 
if (ChildPID == 0) { 
    // will do the computation and automatically set its finish flag. 
    myChild->doComputation(); 
} 
else { 
    while (1) { // your infinite loop in the parent 
     // ... 

     // check if child completed its computation 
     if (myChild->isFinished()) { 
      break; 
     } 
    } 

    // at the end, make sure the child is no runnning, and dispose of the object 
    // when you don't need it. 
    wait(ChildPID); 
    delete myChild; 
} 

esperanza que tiene sentido.

Para reiterar, lo que he escrito anterior es un fea amalgama de C y C++ (no en términos de sintaxis, pero el estilo/diseño), y es justo allí para darle una idea de la sincronización con OO en tu contexto

+0

No estoy seguro de cómo hacer que mi hijo se convierta en un objeto. Esta es la primera vez que hago este tipo de programación, por lo que mi comprensión es bastante básica. En este momento, solo tengo una función principal que crea dos tuberías y luego bifurca y tiene una instrucción if-else usando pid para separar el código de los procesos padre e hijo. ¿Cómo podría hacer para orientar este objeto? – Alex

+0

Si su problema es simple, tal vez ni siquiera necesita hacerlo OO, lo asumí ya que puso C++ como una etiqueta. Realmente depende del problema general que intentas resolver. La respuesta de Erik es la más adecuada para tu código actual. Sin embargo, agregaré algunas cosas a mi respuesta para aclarar. –

+0

Eso tiene sentido. Supongo que realmente es más un problema de C que de C++. Estoy acostumbrado a usar C++ y estoy incluyendo algunas funciones de C++ en mi programa, pero esta parte del programa es más parecida a C. Supongo que en el futuro lo etiquetaré C/C++. – Alex

Cuestiones relacionadas