调用系统后如何启用ctrl-c/ctrl + break? [英] How can I enable ctrl-c / ctrl+break after calling system?

查看:129
本文介绍了调用系统后如何启用ctrl-c/ctrl + break?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个从内部调用系统命令的程序:

I have written a program that invokes a system command from inside:

#include <stdlib.h>

int main(void)
{
    while(1)
    {
        system("ls 2>&1 1>/dev/null"); // comment this line out to enable ctrl+break
    }

    return 0;
}

但是,当它运行时,CTRL + C和CTRL + BREAK不再起作用,并且似乎被忽略了.

However, when it is running, CTRL+C and CTRL+BREAK no longer work and appear to be ignored.

我正在尝试编写一个程序,该程序在涉及shell的后台执行一些操作,但是我也希望能够在用户想要中断时退出该程序.

I am trying to write a program that performs some operations in the background involving the shell, but I also want to be able to break out of the program when the user wants to break.

是否有一种方法可以使它按我想要的方式工作?我应该更改体系结构以执行某种fork/exec吗?

Is there a way to make it work the way I want? Should I change the architecture to perform some kind of fork / exec?

推荐答案

来自 system() 的POSIX规范:

From the POSIX specification for system():

system()函数将忽略SIGINT和SIGQUIT信号,并在等待命令终止时阻止SIGCHLD信号.如果这可能导致应用程序丢失一个将其杀死的信号,则该应用程序应检查 system()的返回值,并在命令由于以下原因而终止时对应用程序采取适当的操作:收到信号.

The system() function ignores the SIGINT and SIGQUIT signals, and blocks the SIGCHLD signal, while waiting for the command to terminate. If this might cause the application to miss a signal that would have killed it, then the application should examine the return value from system() and take whatever action is appropriate to the application if the command terminated due to receipt of a signal.

因此,为了正确响应信号,您需要检查system()的返回值.

So, in order to respond properly to signals, you need to examine the return value of system().

system()以 waitpid()

waitpid()的文档参考 wait()的文档,它指示您使用以下宏来找出退出进程的原因:

And the docs of waitpid() refer to the docs for wait(), which instruct you to use the following macros to find out why a process exited:

  • WIFEXITED(stat_val)
    如果返回正常终止的子进程的状态,则求值为非零值.
  • WEXITSTATUS(stat_val)
    如果WIFEXITED(stat_val)的值不为零,则此宏求值为子进程传递给_exit()或exit()的状态参数的低8位,或者该子进程从main返回的值().
  • WIFSIGNALED(stat_val)
    如果由于收到未捕获的信号而终止的子进程返回状态,则求值为非零.
  • WTERMSIG(stat_val)
    如果WIFSIGNALED(stat_val)的值不为零,则此宏将求值为导致子进程终止的信号编号.
  • WIFSTOPPED(stat_val)
    如果当前停止的子进程返回了状态,则计算为非零值.
  • WSTOPSIG(stat_val)
    如果WIFSTOPPED(stat_val)的值不为零,则此宏将求值为导致子进程停止的信号编号.
  • WIFCONTINUED(stat_val)
    如果从作业控制停止处继续的子流程返回了状态,则评估为非零值.
  • WIFEXITED(stat_val)
    Evaluates to a non-zero value if status was returned for a child process that terminated normally.
  • WEXITSTATUS(stat_val)
    If the value of WIFEXITED(stat_val) is non-zero, this macro evaluates to the low-order 8 bits of the status argument that the child process passed to _exit() or exit(), or the value the child process returned from main().
  • WIFSIGNALED(stat_val)
    Evaluates to non-zero value if status was returned for a child process that terminated due to the receipt of a signal that was not caught (see ).
  • WTERMSIG(stat_val)
    If the value of WIFSIGNALED(stat_val) is non-zero, this macro evaluates to the number of the signal that caused the termination of the child process.
  • WIFSTOPPED(stat_val)
    Evaluates to a non-zero value if status was returned for a child process that is currently stopped.
  • WSTOPSIG(stat_val)
    If the value of WIFSTOPPED(stat_val) is non-zero, this macro evaluates to the number of the signal that caused the child process to stop.
  • WIFCONTINUED(stat_val)
    Evaluates to a non-zero value if status was returned for a child process that has continued from a job control stop.

这里是如何使用此信息而无需分叉单独过程的示例.请注意,您实际上不会在父进程中接收到信号,但是可以确定发送到子进程的信号:

Here is an example of how you would use this information, without having to fork a separate process. Note that you won't actually receive the signal in the parent process, but you can determine the signal sent to the child process:

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    while(1)
    {
        int result = system("ls 2>&1 1>/dev/null");
        if (WIFEXITED(result)) {
          printf("Exited normally with status %d\n", WEXITSTATUS(result));
        } else if (WIFSIGNALED(result)) {
          printf("Exited with signal %d\n", WTERMSIG(result));
          exit(1);
        } else {
          printf("Not sure how we exited.\n");
        }
    }

    return 0;
}

如果运行它,您将得到:

And if you run it, you get:


$ ./sys
Exited normally with status 0
Exited normally with status 0
Exited normally with status 0
Exited normally with status 0
Exited normally with status 0
Exited normally with status 0
^CExited with signal 2

这篇关于调用系统后如何启用ctrl-c/ctrl + break?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆