gpt4 book ai didi

c - c 中的 shell : only respond to SIGTSTP after pressing enter on keyboard

转载 作者:行者123 更新时间:2023-11-30 15:00:17 27 4
gpt4 key购买 nike

我正在尝试用c语言编写一个shell。其中一部分是一个处理程序,用于捕获 SIGTSTP 信号并将其设置为使程序进入和退出仅前台模式。

以下是相关代码片段:

//global variables
int global;

//header
void catch_tstp(int);

//main function
int main(int argc, char** argv){
...

// initiate sigaction struct for CTRL-Z action
struct sigaction ctrlz_act;
ctrlz_act.sa_handler = catch_tstp;
ctrlz_act.sa_flags = SA_SIGINFO|SA_RESTART;
sigfillset(&(ctrlz_act.sa_mask));
sigaction(SIGTSTP, &ctrlz_act, NULL);
global = 0;

...
}

//handler
void catch_tstp(int sig){
if(sig == SIGTSTP){
if(global){
global=0;
printf("Entering foreground-only mode (& is now ignored)\n");
}
else{
global=1;
printf("Exiting foreground-only mode\n");
}
}
}

现在我的输出如下所示:

: ^ZExiting foreground-only mode             //pressed ctrl+z
//nothing here, had to press enter again
: //pressing enter just gives me another :, which is what I want
: ^ZEntering foreground-only mode (& is now ignored)
^ZExiting foreground-only mode

我希望输出可以看起来像这样:

: ^Z
Entering foreground-only mode (& is now ignored)
: //":"should show up own automatically on the next line after I press ctrl-z, then enter
: ^Z
Exiting foreground-only mode
:

谁能指出我做错了什么?任何帮助将不胜感激。谢谢!

最佳答案

您的信号处理程序以及如何设置它存在一些问题。

正如我在评论中已经指出的,只有当该变量是 volatile 时,信号处理程序才能安全地访问文件范围变量,例如global并且类型为sig_atomic_t。如果它尝试访问任何其他变量,则存在看不到为该变量设置的最新值的风险,处理程序范围之外的代码将看不到处理程序写入该变量的值(如果有)变量,并且由于信号处理程序对其进行非原子写入,该变量的值将被损坏。

一个更严重的问题,也已经在注释中指出,是为 sigaction() 指定 SA_SIGINFO 标志,正如您所做的那样,告诉它您已经指定了处理程序通过 struct sigactionsa_sigaction 成员,而您实际上是通过 sa_handler 成员指定的。 如果您通过 sa_handler 指定处理程序,则必须从标志中省略 SA_SIGINFO,反之亦然。如果您不恰本地指定了 SA_SIGINFO 标志,那么接收信号将导致未定义的行为,要么通过使用错误数量的参数调用处理程序,要么尝试通过垃圾函数指针调用函数。

此外,信号处理程序调用的所有函数都必须是异步信号安全的。手册第 7 章中的“signal”条目包含可以安全调用的函数列表,但 printf() 不在其中。

但是干扰你愿望的主要问题是

":"should show up own automatically on the next line after I press ctrl-z

似乎您已在 sigaction 标志中包含 SA_RESTART。该标志会导致(某些)因接收信号而中断的系统函数在信号处理程序完成后自动重新启动,而不是向调用者返回 EINTR 错误或部分结果。在您的特定情况下,如果您的 shell 在读取命令时收到 SIGSTP ,则重新启动读取意味着控制权不会返回到 shell 来打印新的提示符。 这也很可能意味着在 ^Z 之前输入的字符会丢失,具体取决于您如何读取命令的详细信息。

<小时/>

此外,从程序的消息传递来看,您可能对终端接口(interface)和标准 shell 的 ^Z 和 SIGSTP 的含义和使用有误解。它们为 shell 执行的作业提供作业控制功能;它们主要与 shell 本身的模式无关。 shell 无需维护标志或在接收到 ^Z 后表现不同(在信号处理程序本身的范围之外)——所需的交互行为主要源于 shell 可以从标准输入读取的事实仅当它位于前台时。

当 shell 收到 SIGSTP 时,

  • 如果它位于前台,则不应执行任何操作(并避免丢失未处理的输入)。
  • 如果它在后台,它应该向前台进程组发送一个SIGSTOP(注意区别),并在必要时将自己放回前台。在这种情况下,它可能会发出消息和/或提示。

关于c - c 中的 shell : only respond to SIGTSTP after pressing enter on keyboard,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42232257/

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