【问题标题】:Trying to implement an alarm in my shell program. C Signal handling试图在我的 shell 程序中实现警报。 C 信号处理
【发布时间】:2025-03-26 23:00:02
【问题描述】:

我正在用 C 语言构建自己的 shell。我想实现一个名为 alarm 的内置函数,它接受一个整数参数来表示秒数。内置只在 i 秒(一次)后向用户发送一条消息,但同时 shell 功能应该继续工作。

这是我目前所拥有的:

int seconds;

int main(int argc, char const *argv[], char* envp[]){
   ...
   signal(SIGALRM, alarmHandler);
   ...
}

void alarmHandler(int sig) {
    signal(sig, SIG_IGN);
    alarm(seconds);
    printf("%s\n", "message");
    signal(SIGALRM, alarmHandler);
}
void mainProgram(char* string, char* argument){
    ... //built ins that don't require forking
    pid_t processID = fork();

    if(processID==0){ //child
        if(strcmp(string, "alarm") == 0){
            seconds = atoi(argument);
            signal(SIGALRM, alarmHandler);
    }else{ // parent
        usleep(100000)
    }

显然这行不通。我有点迷路了。在过去的几个小时里,我一直在尝试这个,但我不确定该怎么做。

【问题讨论】:

  • “不起作用”不是一个充分的问题描述。请更具体地描述您面临的问题。
  • 好吧,使用上面的代码,没有任何反应。因此,如果我输入警报 4,就好像我只是输入了 enter 并且 shell 会打印出提示符
  • 为什么要在报警处理器中设置报警?除非已经设置了警报,否则不会调用处理程序。

标签: c signals alarm


【解决方案1】:

也许你对 signal 的作用有错误的认识……

signal 系统调用可用于设置信号的处理。一般来说,使用kill系统调用发送信号。

OTOH,也许是 BSD signal handling semanticsSystem V signal handling semantics 之间的区别造成了混乱。 System V 信号处理语义可能需要在信号处理函数中调用signal(再次)。较新的 linux 系统至少坚持使用可靠的 BSD 信号处理语义,并且不需要再次调用 signal,除非您想更改被调用的处理程序。

附带说明一下,一旦您正确使用signal,我建议您改用sigaction。您可以阅读我链接的signal 手册页的“可移植性”部分,了解更多关于为什么应该使用sigaction 而不是signal

但是以后...

除了kill 系统调用之外,还有其他系统调用可用于发送信号。就像您的情况一样,您可能想要使用alarmsetitimer

或者,如果您想实现类似于alarm 所做的事情(不使用alarmsetitimer),您可以使用一个单独的进程(可能通过调用fork)调用睡眠函数然后像这样调用kill

usleep(100000);
kill(pid, SIGALRM);

在本例中,pid 将是您想要向其发送SIGALRM 信号(alarm 发送的信号)的进程的进程 ID。

希望这有助于回答您的问题。

【讨论】:

    最近更新 更多