对于作业,我正在创建一个时间感知的shell。如果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);
}
}
答案 0 :(得分:6)
根据man page:
<强>描述强>
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
答案 1 :(得分: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规范。