Problemas C ++ Fork () e Execv ()
Pergunta
Sou meio novato no C ++ e trabalhando em um programa simples no Linux, que deve invocar outro programa no mesmo diretório e obter a saída do programa invocado sem mostrar a saída do programa invocado no console. Este é o trecho de código em que estou trabalhando:
pid_t pid;
cout<<"General sentance:"<<endl<<sentence<<endl;
cout<<"==============================="<<endl;
//int i=system("./Satzoo");
if(pid=fork()<0)
cout<<"Process could not be created..."<<endl;
else
{
cout<<pid<<endl;
execv("./Satzoo",NULL);
}
cout<<"General sentance:"<<endl<<sentence<<endl;
cout<<"==============================="<<endl;
Um dos problemas que encontro é que sou capaz de imprimir as duas primeiras linhas no console, mas não consigo imprimir as duas últimas linhas. Acho que o programa para de funcionar quando invoco o programa Satzoo. Outra coisa é que esse código invoca o programa Satzoo duas vezes, não sei por quê? Eu posso ver a saída na tela duas vezes. Por outro lado, se eu usar o System () em vez de Execv (), o Satzoo funciona apenas uma vez.
Não descobri como ler a saída do Satzoo no meu programa.
Qualquer ajuda é apreciada.
Obrigado
Solução
Você não está distinguindo entre a criança e o processo pai após a chamada para fork()
. Então, tanto a criança quanto a mãe correm execv()
e assim suas respectivas imagens de processo são substituídas.
Você quer algo mais como:
pid_t pid;
printf("before fork\n");
if((pid = fork()) < 0)
{
printf("an error occurred while forking\n");
}
else if(pid == 0)
{
/* this is the child */
printf("the child's pid is: %d\n", getpid());
execv("./Satzoo",NULL);
printf("if this line is printed then execv failed\n");
}
else
{
/* this is the parent */
printf("parent continues execution\n");
}
Outras dicas
o fork()
funções clones o processo atual e retorna diferente valores em cada processo. No processo "pai", ele retorna o PID da criança. No processo infantil, ele retorna zero. Então você normalmente invocaria usando um modelo como este:
if (fork() > 0) {
cout << "in parent" << endl;
} else {
cout << "in child" << endl;
exit(0);
}
Eu omiti o manuseio de erros acima.
No seu exemplo, os dois caminhos de código acima (pai e filho) caem no else
Cláusula de sua chamada para fork()
, fazendo com que os dois execv("./Satzoo")
. É por isso que seu programa funciona duas vezes e por que você nunca chega às declarações além disso.
Ao invés de usar fork()
E fazer tudo manualmente (gerenciar corretamente a execução do processo é uma quantidade razoável de trabalho), você pode estar interessado em usar o popen()
função em vez disso:
FILE *in = popen("./Satzoo", "r");
// use "in" like a normal stdio FILE to read the output of Satzoo
pclose(in);
De fork()
MANPAGE:
VALOR DE RETORNO
Após a conclusão bem -sucedida, o Fork () retornará 0 ao processo filho e devolverá o ID do processo do processo filho ao processo pai. Ambos os processos devem continuar a executar a partir da função Fork (). Caso contrário, -1 deve ser devolvido ao processo pai, nenhum processo filho será criado e o ERRNO será definido para indicar o erro.
Você verifica para garantir que seja bem -sucedido, mas não se o pid
indica que estamos na criança ou nos pais. Assim, tanto a criança quanto a mãe fazem a mesma coisa duas vezes, o que significa que seu programa é executado duas vezes e o texto final nunca será impresso. Você precisa verificar o valor de retorno de fork()
mais do que apenas uma vez.
EXEC - A família de funções EXEC () substitui a imagem atual do processo por uma nova imagem de processo.
Sistema - Bloco na execução do comando. A execução do programa de chamada continua após o retorno do comando do sistema
Existem três testes de valor de retorno que você deseja com o garfo
- 0: você é a criança
- -1: erro
- outro: você é o pai
Você executou o outro programa da criança e do pai ...