4

对于一项任务,我正在创建一个时间感知外壳。如果命令运行超过设定的时间,shell 会分叉并执行命令并杀死它们。例如。

 input# /bin/ls
 a.out code.c
 input# /bin/cat
 Error - Expired After 10 Seconds.
 input#

现在,我的问题是:如果在程序处理过程中发生错误,即exevce返回-1时,有没有办法防止警报启动?

由于子进程是单独运行的,经过数小时的试验和研究,我还没有找到任何讨论甚至暗示这类任务的东西,我觉得这可能是不可能的。如果确实不可能,我该如何防止发生类似以下的事情......

 input# /bin/fgdsfgs
 Error executing program
 input# Error - Expired After 10 Seconds.

对于上下文,这是我目前正在使用的代码,我自己尝试这样做的尝试被删除。我在这里先向您的帮助表示感谢!

while(1){
    write(1, prompt, sizeof(prompt)); //Prompt user
    byteCount = read(0, cmd, 1024); //Retrieve command from user, and count bytes
    cmd[byteCount-1] = '\0';    //Prepare command for execution

    //Create Thread
    child = fork();

    if(child == -1){
        write(2, error_fork, sizeof(error_fork));
    }

    if(child == 0){ //Working in child
        if(-1 == execve(cmd,arg,env)){  //Execute program or error
            write(2, error_exe, sizeof(error_exe));
        }   
    }else if(child != 0){   //Working in the parent
        signal(SIGALRM, handler);   //Handle the alarm when it goes off
        alarm(time);
        wait();
        alarm(0);
    }
}
4

2 回答 2

7

根据手册页

描述

在经过 seconds 指定的实时秒数后,alarm() 函数应使系统为进程生成 SIGALRM 信号。处理器调度延迟可能会阻止进程在信号生成后立即对其进行处理。

如果秒为 0,则取消挂起的警报请求(如果有)。

报警请求不堆叠;以这种方式只能安排一次 SIGALRM 生成。如果尚未生成 SIGALRM 信号,则调用将导致重新安排生成 SIGALRM 信号的时间。

未指定 alarm() 与 setitimer()、ualarm() 或 usleep() 中的任何一个之间的交互。

因此,要取消警报:alarm(0). 它甚至出现在您的示例代码中。

主要问题

顺便说一句,你在这里错过了一个重要的部分:

if(child == 0){ //Working in child
    if(-1 == execve(cmd,arg,env)){  //Execute program or error
        write(2, error_exe, sizeof(error_exe));
        _exit(EXIT_FAILURE);  // EXIT OR A FORKED SHELL WILL KEEP GOING
    }   
}else if(child != 0){   //Working in the parent
于 2012-04-19T23:51:20.217 回答
1

系统wait()调用接受一个参数;为什么不使用源文件中的正确头文件和未声明函数的编译器警告(最好是错误)进行编译?或者,如果您收到此类警告,请在提交代码以在 StackOverflow 等地方进行审核之前注意它们。

您不需要测试execve()(或任何exec*()函数)的返回状态;如果返回,则失败。

在失败时写一个错误是很好的。如果子进程也退出会更好,这样它就不会回到while (1)循环中,与你的主 shell 竞争输入数据。

if (child == 0)
{
    execve(cmd, arg, env);
    write(2, error_exe, sizeof(error_exe));
    exit((errno == ENOEXEC) ? 126 : 127);
}

事实上,你的孩子不退出是你问题的主要原因;由于孩子尚未退出,因此等待直到警报响起才返回。显示的退出状态旨在匹配POSIX shell规范。

于 2012-04-20T00:10:16.333 回答