gpt4 book ai didi

C - 优雅地中断 msgrcv 系统调用

转载 作者:行者123 更新时间:2023-11-30 15:22:21 25 4
gpt4 key购买 nike

我正在开发一个程序,该程序应该像服务器一样运行,不断从消息队列中读取并处理收到的消息。

主循环看起来像这样:

while (1) {
/* Receive message */
if (msgrcv(msqid, &msg, sizeof(struct msgbuffer) - sizeof(long), 0, 0) == -1) {
perror("msgrcv");
exit(1);
}
//more code here
}

我遇到的问题是,我无法找到一种方法来优雅地退出此循环,而不依赖客户端向服务器发送消息来指示它应该停止。我在循环后做了很多资源清理,但我的代码永远无法达到这一点,因为循环不会结束。

我尝试做的一件事是监听 SIGINT 来结束循环......

volatile sig_atomic_t stop;

void end(int signum) {
stop = 1;
}

int main(int argc, char* argv[]) {
signal(SIGINT, end);
//some code
while (!stop) {
/* Receive message */
if (msgrcv(msqid, &msg, sizeof(struct msgbuffer) - sizeof(long), 0, 0) == -1) {
perror("msgrcv");
exit(1);
}
//more code here
}
//cleanup
}

...但是由于循环卡在系统调用本身上,因此这不起作用,只会导致 perror 打印出 msgrcv: Interrupted system call ,而不是终止循环并清理我的资源。

有没有办法可以终止系统调用并优雅地退出循环?

解决方案:

感谢 rivimey,我能够解决我的问题。以下是我为使其发挥作用所做的工作:

volatile sig_atomic_t stop;

void end(int signum) {
stop = 1;
}

int main(int argc, char* argv[]) {
signal(SIGINT, end);
//some code
while (!stop) {
/* Receive message */
if (msgrcv(msqid, &msg, sizeof(struct msgbuffer) - sizeof(long), 0, 0) == -1) {
if (errno == EINTR) break;
else {
perror("msgrcv");
exit(1);
}
}
//more code here
}
//I can now reach this code segment
}

最佳答案

您最好看看现有的软件可以做到这一点;这是一种非常常见的模式,但并不像您希望的那样简单。但基本原理是:

  • 信号处理程序 - 它不会有帮助(正如您所发现的)
  • 检查 msgrcv() == EINTR 返回的错误号;如果是这样,您就看到了中断。
  • 请注意,如果 msgrcv 在中断时收到了部分但不是全部消息,您将必须清理自己的状态和发送者。
  • 最后,您可能会发现有时会调用信号处理程序 - 如果中断发生在用户代码运行时而不是系统调用时。而且 msgrcv 并不是唯一的系统调用...我确实说过它很复杂。

对于一个不平凡的程序,你最好使用“毒药”方法来终止循环。使用 msgsend 向自己发送一条消息,内容是“杀掉我”。这样,您就可以获得可预测的结果。

HTH,露丝

关于C - 优雅地中断 msgrcv 系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29245596/

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