如何在通过exec调用的父进程中获取已执行应用程序的状态?
我正在开发一个简单的应用程序,它可以完成以下任务:如何在通过exec调用的父进程中获取已执行应用程序的状态?,c,linux,fork,exec,embedded-linux,C,Linux,Fork,Exec,Embedded Linux,我正在开发一个简单的应用程序,它可以完成以下任务: 主应用程序将具有子进程,其中在am中通过exec调用调用应用程序。此应用程序实际上正在执行固件下载操作。 例如execl(“/usr/bin/fwdownload”,“fwdownload”,“args”,NULL) 在父进程中,我将再次分叉它,以便再次拥有子进程。在这个子进程中,我调用Xmodem实用程序从本地机器接收固件映像文件。我将收到的数据包写入命名的fifo文件(使用mkfifo创建)。“fwdownload”应用程序将访问此命名的f
void SIGTERM_Handler(int signal)
{
exit(0); // Kill the Xmodem utility
}
int main()
{
pid_t cpid_1, cpid_2 ;
cpid_1 = fork();
if( cpid_1 == 0 ) // child process
{
execl("/usr/bin/fwdownload", "fwdownload", NULL);
printf("exec Failed");
exit(FAILED);
}
else // Parent process
{
cpid_2 = fork();
if( cpid_2 == 0 )
{
mkfifo("/tmp/fifo_file");
signal(SIGTERM, SIGTERM_Handler);
execl("/bin/rx", "rx", "/tmp/fifo_file", NULL); // fifo_file
printf("exec failed");
exit(FAILED);
}
else
{
wait_status = waitpid(cpid_1, &status, WUNTRACED | WCONTINUED);
if( WIFEXITED(status))
{
kill(cpid_2, SIGTERM);
printf(" FW Download app is exited \n");
}
}
}
}
要获取已终止进程的状态,可以使用WEXITSTATUS(status)宏。此宏将为您提供子进程返回的代码 在调用execl之前捕获信号也是无用的,因为(摘自execve手册页): 正在捕获的任何信号的处理将重置为默认值(信号(7)) 在您的情况下,您会得到以下代码:
int main()
{
pid_t cpid_1, cpid_2 ;
cpid_1 = fork();
if( cpid_1 == 0 ) // child process
{
execl("/usr/bin/fwdownload", "fwdownload", NULL);
printf("exec Failed");
exit(FAILED);
}
else // Parent process
{
cpid_2 = fork();
if( cpid_2 == 0 )
{
mkfifo("/tmp/fifo_file");
//signal(SIGTERM, SIGTERM_Handler);
execl("/bin/rx", "rx", "/tmp/fifo_file", NULL); // fifo_file
printf("exec failed");
exit(FAILED);
}
else
{
wait_status = waitpid(cpid_1, &status, WUNTRACED | WCONTINUED);
if( WIFEXITED(status) && WEXITSTATUS(status) != 0)
{
kill(cpid_2, SIGTERM);
printf(" FW Download app is exited \n");
}
}
}
}
为什么子进程之间是FIFO而不是管道?还是一个普通的文件?我个人从不认为固件传输成功,并且总是希望固件安装程序应用程序检测固件下载是否失败或中断(例如,由于网络中断或其他原因)。如果固件安装程序总是将整个映像读取到内存中(因为它的某处有一个校验和),那么它确实应该支持从标准输入读取数据。如果不是,我肯定会使用一个临时文件和单独的sha256sum校验和…我不使用普通文件,因为fwdownload应用程序希望文件传输是在分组事务中进行的。我没有任何理由不使用管道。如果我们使用普通管道而不是FIFO文件,我们有什么额外的好处吗。使用管道有几个优点。如果下载应用程序死亡/退出,安装程序将通过下一步
read()
返回0来检测它。如果安装程序死亡/退出,下载应用程序将从下一个write()
中获得-1,其中errno==EPIPE
。如果使用FIFO,另一端也将阻塞,直到另一端打开,并且始终存在其他过程干预的风险(通过同时打开FIFO);此外,必须根据需要创建和删除FIFO文件系统对象。简单地说,FIFO更复杂,风险更大,在这个用例中没有好处。非常感谢。是的,你是对的。就我而言,我怀疑有一个死锁正在发生。当写入FIFO的进程启动时,必须同时执行从同一FIFO读取的其他进程。但在我的例子中,第二个进程(从FIFO读取)正在退出或返回,这将使第一个进程处于阻塞状态。因此,你建议我,如果我们使用管道,这种情况不会发生。如果两个程序在退出之前都显式关闭管道,则不应发生这种情况。写入程序(下载程序)将阻塞,直到读卡器(安装程序)读取数据为止(每个管道都有至少512字节的缓冲区,只要管道的另一端仍然打开,就可以“立即”写入);读卡器将阻塞,直到写入器关闭管道或写入更多数据。你有没有考虑过编写一个最小的测试程序——比如说,如果孩子们看到数据中的某个特定字符,就退出这个程序,睡在其他字符上,否则就不会做真正的工作?根据我的理解,signal()系统调用将注册该进程的指定信号,如果该信号发生,则相应的信号处理程序将处理该信号。正如您提到的,signal()不是用来捕捉信号的。这只是为了注册特定的信号。如果我错了,请纠正我,我的朋友。