gpt4 book ai didi

c - 设计shell时如何处理Control-C信号?

转载 作者:太空宇宙 更新时间:2023-11-04 03:09:52 25 4
gpt4 key购买 nike

我正在尝试实现 shell 中存在的一些功能,包括仅在用户输入 quit 而不是 Ctrl+C 时退出。下面是我尝试过的代码的简化版本。

代码 1:没有在信号处理程序中调用 loop()。

void loop(){
while(1){
char a[20];
printf("Enter Command : " );
scanf("%s",a);
printf("%s\n", a);
}
}

void sigintHandler(int sig_num)
{
signal(SIGINT, sigintHandler);
printf("\n");
}

int main(int argc, char const *argv[]) {

signal(SIGINT, sigintHandler);
loop();
return 0;
}

代码1的输出:

enter image description here

从第三个输入可以看出,我换了一行并从我离开循环的地方继续。我想重新开始循环。因此,我通过在信号处理程序本身中调用循环进行了以下修改。

void loop(){
while(1){
char a[20];
printf("Enter Command : " );
scanf("%s",a);
printf("%s\n", a);
}
}

void sigintHandler(int sig_num)
{
signal(SIGINT, sigintHandler);
printf("\n");
loop();
}

int main(int argc, char const *argv[]) {

signal(SIGINT, sigintHandler);
loop();
return 0;
}

代码 2 的输出:

enter image description here

可以看出,当我第一次点击 Ctrl+C(在输入行 3 上)时,它工作正常,我可以继续。但是,当我第二次单击 Ctrl+C 时,我没有换行,我必须按 enter 键才能执行程序。

我经历了this问题,但它似乎不适用于我的情况。这是我第一次使用信号和系统调用,所以我的问题可能很愚蠢。但是,如果有人可以帮助我找到正确的信号实现方式,那将是一个很大的帮助。谢谢。

最佳答案

Jonathan Leffler 提供了有用的提示(尽管还不够,至少在一些流行的操作系统上):

  • 看看 scanf() 返回什么。
  • 不要在信号处理程序中使用 loop()
  • 不要使用 signal() — 使用 sigaction()。在您的情况下,这有两个优点:
    • 可以避免在调用信号处理程序时将信号操作恢复为默认状态,因此您不必在处理程序中再次更改操作。
    • 可以避免重新启动 read() 系统调用(在 scanf() 内),以便 scanf() 返回 并且您可以首先对中断使用react。

所以,信号处理程序可以只是

void sigintHandler(int sig_num)
{
printf("\n"); // or perhaps better write(1, "\n", 1)
}

main()中的signal(SIGINT, sigintHandler);可以替换为

  sigaction(SIGINT, &(struct sigaction){ .sa_handler = sigintHandler }, NULL);

scanf("%s",a);

      if (scanf("%s", a) == EOF)
{
if (errno == EINTR) continue; // read operation interrupted by signal
return;
}

EOF 在中断和文件结束时返回,所以要通过errno 来区分。此外,如果您的程序提供一种退出它的方法,那就太好了,因此 return

关于c - 设计shell时如何处理Control-C信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57480852/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com