2016-09-29 4 views
0

Я создал несколько дочерних процессов fork() и запустил их исполняемый файл execl().Как проверить успешность execl() (несколько процессов)

Я хочу проверить, нет ли какого-либо execl(), который не работает (например: попробуйте выполнить файл, не существующий). Попробуйте выполнить execl() все программы, и если один из них потерпит неудачу, верните 1 до начала связи с любыми программами.

здесь код ссылки, (предположим, что все регулировками правильны)

#DEFINE NUMBEROFCHILD 4 
char** exeFile = {"./p1", "./p2", "./p3", "nonexist"); //"nonexist" is a non-exist program 
int main(int argc, char** argv){ 
    pid_t childPID [numberOfChild]; 

    for (int i = 0; i<numberOfChild; i++) { 
      //setting up pipes 
      pid_t childPID[i] = fork(); 

      if(childPID[i] < 0) { 
       //close all pipes and quit 
      }else if (childPID[i] == 0) { 
       //redirect pipe 
       execl(exeFile[i],"args",(char*)0; 
       return 1; 
       //I'm expecting this to return when it try to execute "nonexist" 
       //but it didn't and keep running successed execl() 
      }else { 
       //close un-use pipes 
      } 
    } 

    while(true) { 
      for (int i = 0; i<numberOfChild; i++) { 
       //communicate with childs through pipe 
      } 
    } 

    for (int i = 0; i<numberOfChild; i++) { 
      //close reminded pipes 
      if (waitpid(childPID[i], NULL, 0) == -1){ 
       return 1; 
      } 
    } 
    return 0; 
} 

Эта программа еще послал сообщение «nonexist» (но ничего не получить обратно от него, как ожидают).

Возможно, когда-либо достигли моей цели? Спасибо!

+0

Поместите 'printf' перед' return 1', чтобы увидеть, что 'execl' не удалось. Имейте в виду, что в данный момент вы находитесь в дочернем процессе, поэтому вам нужно будет использовать каналы для связи с родителем или отправить сигнал типа 'kill (getppid(), SIG_USER1)' или использовать любые количество других межпроцессных средств связи. – user3386109

+0

Семейство функций 'exec *' возвращается к ошибке -1, а 'errno' задается для указания ошибки. Проверьте возвращаемое значение 'execl' (в основном' execl' будет возвращаться только при ошибке). – Pablo

+0

Когда исполняемый файл не найден, 'execl' вернет 2 (' ENOENT') – Pablo

ответ

2

Вы можете устроить, чтобы дать ребенку один конец pipe(), установленный к закрытию-exec.

После отказа execl() (т. Е. Если звонок возвращается), ребенок будет write() в трубу. Если родитель получает что-либо на своем конце трубы (проверка с помощью poll() или аналогичная), то он знает, что ребенок потерпел неудачу.

Если сообщение от дочернего элемента содержит идентификатор дочернего элемента, тогда канал может быть общим для всех дочерних элементов. Постарайтесь держать write() достаточно маленьким, чтобы быть атомарным!

+0

Сохранение записи достаточно мало, не сложно; вам придется писать более 4 килобайт - возможно, более 64 килобайт - превышать предел для атомной записи на трубе. –

+0

Да, я должен был сказать, что было бы очень дико писать так много! –

+0

Насколько это устойчиво при наличии произвольных задержек планирования? Как долго родительский процесс ждет, прежде чем решить, что все дети преуспели? Это не так сильно, как положительное сообщение от детей «Я здесь». Но мы не знаем, могут ли дочерние процессы модифицироваться, чтобы они могли отправить положительное сообщение. Мы не знаем, какие каналы настроены либо: есть ли канал от родителя до ребенка, или от ребенка до родителя, или пара трубок по одному в каждом. Это немного сложнее. –

0

Единственный надежный (но довольно экзотический, возможно, не очень портативный) способ достижения вашей цели - использовать ptrace. Родитель устанавливает PTRACE_TRACEEXEC вариант, вилки всех детей и wait() в цикле. Ребенок делает

} else if() { 
     ptrace(PTRACE_TRACEME, ...); 
     execl(...); 
    } 

родительскую должен держать зацикливание wait, пока все дети не сообщают ни PTRACE_EVENT_EXEC или выход. В первом случае exec был успешным, и ребенок остановился. Когда вы знаете, что каждый ребенок сообщил, и вы удовлетворены их состоянием, сделайте ptrace(PTRACE_DETACH, ...) на все и продолжайте по желанию.