system 调用 Qt 程序的问题

system 调用 Qt 程序的问题

在公司做了一个嵌入式系统的引导程序,进程在系统开始后自启动(这里使用的是 rc.local 添加启动项的方法),随后按照相应的顺序依次启动相应的程序,之前一直没有出现什么问题,直到增加了一个启动 Qt 程序,并监控程序状态的需求后,出现了一些无法解释的问题。

编写代码的过程

  • 第一个需求:进程中调用一个 Qt 程序。

这个代码很简单,为了省事,简单使用了 system() 函数。

    system("QtApplication -qws");
  • 第二个需求:需要获取 QtApplication 的返回值。

system 函数的执行过程分为三个步骤:
1. 创建一个子进程,主要是 fork() 等过程。
2. 调用 /bin/sh 拉起 shell 脚本。
3. 执行相应的 shell 脚本,waitpid()。

因此,system 的返回值(status)囊括了以上三个步骤的结果:
1. 如果调用子进程失败,或者 waitpid() 返回除了 EINTR 之外的错误,system 返回 -1;
2. 如果 shell 拉起失败或未正常执行结束(只要能够调用到 /bin/sh,并且执行shell过程中没有被其他信号异常中断,都算正常结束),原因值被写入到status的低8~15比特位中。
系统提供了宏:WIFEXITED(status) 来判断 shell 的执行结果。如果 WIFEXITED(status) 为真,则说明正常结束。
3. 如果 shell 脚本正常执行结束,将 shell 返回值填到 status 的低8~15比特位中。
同样系统提供了宏:WEXITSTATUS(status) 来获取相应脚本的执行结果。

一个简单的执行代码如下, 因为程序需要执行一段时间,所以添加了一个轮询:

int system_call()
{
    int status = 9;
    status = system("QtApplication -qws");
    for(int i = 0; i < 6000; i++)
    {
        if(status != 9)
        {
            if( -1 == status) //status == -1, 子进程创建失败
            {
                printf("system error!"); 
                return -1;
            }
            else
            {
                if(WIFEXITED(status)) //WIFEXITED(status) 为真,QtApplication 成功执行
                {
                    if(0 == WEXITSTATUS(status))
                    {
                        printf("QtApplication successfully.\n"); //Qt 程序执行成功
                        return 0;
                    }
                    else
                    {
                        printf("QtApplication failed, exit code: [%d]\n", WEXITSTATUS(status));//Qt 程序执行失败,获取失败返回值。
                        return -1;
                    }
                }
                else
                {
                    printf("exit status = [%d]\n", WEXITSTATUS(status)); //WIFEXITED(status) 不为真,shell 调用失败。
                    return -1;
                }
            }
        }
        usleep(100);
    }
    return -1;
}

出现的问题

编写完这个代码后简单的执行,调试,没有发现什么问题,所以开始进行测试,结果出现一个很奇怪的现象:
当 Qt 程序没有执行完成的时候,system 返回了程序的返回值,并打印了以下的语句:exit status = [0]

更为奇怪的是同样的问题,当手动执行 system_call 的时候,并不会出现这样的问题。

为什么会出现这样的问题?

经过对系统代码的分析,发现,在系统启动时启动一个拨号程序,而这个程序在系统启动大概200ms的时候杀死了所有的 sh 程序。

问题的解决

因为拨号程序不能更改,所以只能先通过 exec 的方法调用程序,毕竟system()函数用起来很容易出错!!!

于是,尝试了使用 exec 直接执行的方式来调用子程序,代码如下:

int system_call()
{
    pid_t pid, ret;
    int status;
    if((pid = fork()) < 0)
    {
        printf("Fork Failed!");
        return -1;
    }
    else if(pid == 0)
    {
        if((status = execlp("QtApplication", "QtApplication", "-qws", NULL)) < 0)
        {
            printf("EXEC Failed!");
        }
    }
    else
    {
        for(int i = 0; i < 6000; i++)
        {
            ret = waitpid(pid, &status, WNOHANG);
            if(ret == pid)
            {
                if(WIFEXITED(status))
                {
                    if(0 == WEXITSTATUS(status))
                    {
                        printf("QtApplication successful", 3);
                        return 0;
                    }
                    else
                    {
                        printf("tcu_update failed with CODE[%d]",  WEXITSTATUS(status));
                        return -1;
                    }
                }
                else
                {
                    printf("tcu_update start failed with CODE[%d]",  WEXITSTATUS(status));
                    return -2;
                }

            }
            usleep(100000);
        }
        return -2;
    }

}

参考:

【C/C++】Linux下system()函数引发的错误)
【C/C++】Linux下system()函数引发的错误

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值