在公司做了一个嵌入式系统的引导程序,进程在系统开始后自启动(这里使用的是 rc.local 添加启动项的方法),随后按照相应的顺序依次启动相应的程序,之前一直没有出现什么问题,直到增加了一个启动 Qt 程序,并监控程序状态的需求后,出现了一些无法解释的问题。
编写代码的过程
- 第一个需求:进程中调用一个 Qt 程序。
这个代码很简单,为了省事,简单使用了 system()
函数。
system("QtApplication -qws");
- 第二个需求:需要获取 QtApplication 的返回值。
system 函数的执行过程分为三个步骤:
- 创建一个子进程,主要是
fork()
等过程。 - 调用
/bin/sh
拉起 shell 脚本。 - 执行相应的 shell 脚本,waitpid()。
因此,system 的返回值(status)囊括了以上三个步骤的结果:
- 如果调用子进程失败,或者 waitpid() 返回除了
EINTR
之外的错误,system 返回 -1; - 如果 shell 拉起失败或未正常执行结束(只要能够调用到
/bin/sh
,并且执行shell过程中没有被其他信号异常中断,都算正常结束),原因值被写入到status的低8~15比特位中。
系统提供了宏:WIFEXITED(status)
来判断 shell 的执行结果。如果WIFEXITED(status)
为真,则说明正常结束。 - 如果 shell 脚本正常执行结束,将 shell 返回值填到 status 的低8~15比特位中。
同样系统提供了宏:WEXITSTATUS(status)
来获取相应脚本的执行结果。
一个简单的执行代码如下, 因为程序需要执行一段时间,所以添加了一个轮询:
出现的问题
编写完这个代码后简单的执行,调试,没有发现什么问题,所以开始进行测试,结果出现一个很奇怪的现象:
当 Qt 程序没有执行完成的时候,system 返回了程序的返回值,并打印了以下的语句:exit status = [0]
更为奇怪的是同样的问题,当手动执行 system_call 的时候,并不会出现这样的问题。
为什么会出现这样的问题?
经过对系统代码的分析,发现,在系统启动时启动一个拨号程序,而这个程序在系统启动大概200ms的时候杀死了所有的 sh 程序。
问题的解决
因为拨号程序不能更改,所以只能先通过 exec 的方法调用程序,毕竟system()函数用起来很容易出错!!!
于是,尝试了使用 exec 直接执行的方式来调用子程序,代码如下: