system调用总是返回-1

本文揭示了在daemon程序中使用system调用执行脚本时返回-1的原因,并提供了解决方案及正确判断脚本执行状态的方法。
在一个daemon程序中调用system来执行一段脚本,返回值总是-1.脚本简单的不能再简单了,只有一句exit 0,但还是返回-1.
查了很多资料,也没能找出原因,最后经过我反复的调试,终于发现了一个惊天动地的秘密!!

返回-1的原因是因为进程将SIGCHLD屏蔽了!!

确实我的程序在main函数里面就调用signal(SIGCHLD, SIG_IGN);将SIGCHLD屏蔽了!
system的调用过程主要是调三个函数
1.fork()
2.execl()
3.wait()
wait需要依赖SIGCHLD信号,所以屏蔽了SIGCHLD信号就永远得不到system正确的返回值了!

另外附一段正确判断脚本执行的方法:
system的返回值是按不同的字节置位的,0~7位和8~15位置的是不同的内容,判断脚本是否正确执行的正确做法是:

(1)-1 != status
(2)WIFEXITED(status)为真
(3)0 == WEXITSTATUS(status)

下面来解释一下后两个返回值的含义:

1,WIFEXITED(status) 这个宏用来指出子进程是否为正常退出的,如果是,它会返回一个非零值。

2,WEXITSTATUS(status) 当WIFEXITED返回非零值时,我们可以用这个宏来提取子进程的返回值,如果子进程调用exit(5)退出,WEXITSTATUS(status)就会返回5;如果子进程调用exit(7),WEXITSTATUS(status)就会返回7。



最后写了一段小的测试程序:
#include <iostream>
using namespace std;
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    cout<<"pid: "<<getpid()<<endl;
    int ret = 0;
    signal(SIGCHLD, SIG_IGN);
    ret = system("./wyf.sh");
    cout<<"ret: "<<ret<<endl;
    return 0;
}

这段代码在2.6内核的系统上总是返回-1,但是奇怪的是在2.4内核的系统上返回0.
<think>嗯,用户问的是system()函数返回-1的原因和解决方法。我需要先回忆一下system()函数的工作原理。system()函数是C标准库中的一个函数,用于执行命令行指令。它会调用fork()创建子进程,然后子进程调用execl()来执行shell,而shell再去执行用户传入的命令。父进程则等待子进程结束,并获取返回值。 根据引用中的内容,用户提到了返回-1的情况。根据引用[2],当system()返回-1时,可能是fork()失败导致的。fork()失败通常是因为系统资源不足,比如进程数达到上限、内存不足等。这时候需要检查系统资源使用情况,比如用top或ps命令查看进程数量,或者检查内存和交换空间。 另外,引用[3]提到SIGCHLD信号的处理方式也可能影响system()的返回值。如果SIGCHLD被设置为SIG_IGN(忽略),可能会导致waitpid()无法正确获取子进程状态,从而返回ECHILD错误,进而让system()返回-1。解决办法是在调用system()之前,将SIGCHLD的处理方式恢复为默认的SIG_DFL,即使用signal(SIGCHLD, SIG_DFL)。 还有可能的情况是路径问题,比如要执行的命令不存在或者权限不足。这时候需要检查命令的绝对路径是否正确,以及是否有执行权限。可以使用which命令确认路径,并用chmod添加执行权限。 此外,环境变量的问题也可能导致命令找不到,比如在非交互式shell中环境变量可能不同。这时可以指定绝对路径,或者在system()调用中设置完整的PATH变量。 总结起来,解决步骤应该是:首先检查fork失败的可能原因,比如资源不足;然后检查SIGCHLD信号设置;接着验证命令的路径和权限;最后检查环境变量是否正确。需要逐步排查这些可能性。 用户可能是在开发过程中遇到了system()返回-1的问题,特别是在嵌入式系统或资源受限的环境中,资源不足的情况更常见。另外,如果他们的程序中有自定义的信号处理,可能会无意中修改了SIGCHLD的处理方式,导致问题。需要提醒用户检查这些方面,并提供具体的命令和代码示例,比如如何设置信号处理,如何检查进程数等。</think>### system()函数返回-1的原因及解决方案 #### 一、核心原因分析 1. **`fork()`系统调用失败** 当`system()`函数尝试创建子进程时,若`fork()`失败(如系统进程数达到上限、内存不足),会直接返回`-1`[^2][^3]。可通过以下命令检查系统资源状态: ```bash ulimit -u # 查看用户进程数限制 free -h # 查看内存使用情况 ps aux | wc -l # 统计当前进程数 ``` 2. **SIGCHLD信号处理异常** 若父进程将`SIGCHLD`信号设置为`SIG_IGN`(忽略子进程终止信号),可能导致`waitpid()`无法获取子进程状态,从而触发`ECHILD`错误并返回`-1`[^3]。示例修复代码: ```c signal(SIGCHLD, SIG_DFL); // 恢复默认信号处理 int status = system("your_command"); ``` 3. **命令执行环境异常** - 命令路径错误(如未使用绝对路径) - 权限不足(如未添加可执行权限) - 环境变量缺失(如`PATH`未包含命令所在目录) --- #### 二、解决方案步骤 1. **检查系统资源限制** ```bash # 查看进程数限制 cat /proc/sys/kernel/pid_max # 临时提高进程数限制 ulimit -u 10000 ``` 2. **验证SIGCHLD信号处理** 在调用`system()`前重置信号: ```c #include <signal.h> // 主函数初始化时添加 signal(SIGCHLD, SIG_DFL); ``` 3. **调试命令执行问题** - **使用绝对路径** ```c system("/usr/bin/your_command"); // 替换为实际路径 ``` - **检查权限** ```bash chmod +x /path/to/your_command ``` - **显式设置环境变量** ```c system("PATH=/usr/local/bin:/usr/bin:/bin; your_command"); ``` --- #### 三、代码验证示例 ```c #include <stdio.h> #include <stdlib.h> #include <signal.h> int main() { signal(SIGCHLD, SIG_DFL); // 关键修复点 int ret = system("/usr/bin/date"); if (ret == -1) { perror("system() failed"); exit(EXIT_FAILURE); } return 0; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值