You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux Posix消息队列问题:父进程无法打印子进程发送的素数

问题排查与修复方案

1. 格式符不匹配导致素数筛选失效

代码中使用 %ld 读取 int64_t 类型变量,但 %ld 对应**long int**,而 int64_t 的标准格式符应为 %lld(或引入 <inttypes.h> 头文件后使用 PRId64 宏更规范)。格式符不匹配会导致读取的数值错误,进而让 isPrime 函数无法正确识别素数,最终没有任何消息发送到队列,父进程自然不会打印内容。

修复:

// 先引入头文件
#include <inttypes.h>

// 替换读取时的格式符
while (fscanf(file, "%" PRId64, &number) == 1) {

或直接使用 %lld(适用于多数64位系统):

while (fscanf(file, "%lld", &number) == 1) {

2. 父进程消息处理逻辑错误

父进程依赖 mq_getattr 轮询队列消息数的逻辑存在两个致命问题:

  • 队列空时,父进程会持续空转,不会阻塞等待子进程发送消息;
  • 所有子进程退出后,父进程会无限循环(mq_getattr 始终返回0),无法正常终止。

正确做法是先等待所有子进程退出,再阻塞读取队列剩余消息:

// 记录子进程PID
pid_t child_pids[N];
for (int i = 0; i < N; i++) {
    pid_t pid = fork();
    if (pid < 0) {
        perror("Fork failed");
        exit(EXIT_FAILURE);
    } else if (pid == 0) {
        // 子进程原有逻辑不变
        // ...
    } else {
        child_pids[i] = pid;
    }
}

// 等待所有子进程退出
for (int i = 0; i < N; i++) {
    waitpid(child_pids[i], NULL, 0);
}

// 读取队列中所有剩余消息
int64_t number;
ssize_t recv_len;
while ((recv_len = mq_receive(mq, (void *)&number, sizeof(number), NULL)) != -1) {
    if (recv_len == sizeof(number)) {
        printf("%lld\n", number); // 注意格式符匹配
    }
}

// 验证退出原因是否为队列空
if (errno == ENOMSG) {
    printf("所有消息处理完毕\n");
} else {
    perror("mq_receive failed");
}

3. 缺少系统调用错误检查

代码多处未检查系统调用返回值,无法及时发现问题:

  • 检查 mq_open 是否成功:
mq = mq_open(MQ_NAME, O_CREAT | O_RDWR, 0644, &mq_attributes);
if (mq == (mqd_t)-1) {
    perror("mq_open failed");
    exit(EXIT_FAILURE);
}
  • 检查 mq_send 是否成功:
if (mq_send(mq, (void *)&number, sizeof(number), 0) == -1) {
    perror("mq_send failed");
    // 可根据场景选择退出或重试
}

4. 消息队列容量限制

确保 M(mq_maxmsg)的取值不超过系统限制,可通过 /proc/sys/fs/mqueue/msg_max 查看系统默认上限,避免因队列容量过小导致消息发送阻塞或失败。


内容的提问来源于stack exchange,提问作者DenizTuna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 15:43:14