在进程被阻止时,将消息队列中的attr更改为O_NONBLOCK

时间:2018-01-20 18:28:19

标签: c posix message-queue

我有一些使用POSIX消息队列的进程,当错误处理我希望所有进程都关闭时。麻烦的是,有时它们没有自己完成,并且当队列已满时在mq_send上被阻塞(或者当它为空时在mq_receive上被阻塞)。在彻底阅读文档后,我注意到有一种方法可以阻止阻塞,即用O_NONBLOCK设置mq_setattr()标志。虽然大多数情况下接收错误的过程应该足够快,并设置标志以便进程永远不会挂起来等待它,但是不能确定是这种情况。所以我想知道当属性设置为非阻塞时,已经等待的进程是否会被唤醒,并且我编写了以下程序来验证它没有。该计划是否正确?除了手动调用mq_receive()以便在mq_maxmsg == mq_curmsgs或向他们发送信号时人为降低消息数量时,可以采取其他措施吗?

#include <stdio.h>
#include <mqueue.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>

void system_err (char* fmt, ...) {
    va_list fmt_args;
    fprintf(stderr, "ERROR: ");
    va_start(fmt_args, fmt);
    vfprintf(stderr, fmt, fmt_args);
    va_end (fmt_args);
    fprintf(stderr," (%d; %s)\n", errno, strerror(errno));
    exit(1);
}
int main() {
    struct mq_attr a;
    a.mq_flags = O_NONBLOCK;
    char bfr[819300];
    unsigned int prio = 69;
    int x;
    switch (fork()) {
        case -1:
            system_err("oops");
            break;
        case 0:
            sleep(1);
            x = mq_open("/lol", O_RDWR);
            if (x == -1) {
                system_err("childoops");
                return -1;
            }
            x = mq_receive(x, bfr, sizeof(bfr), &prio);
            if (x == -1) {
                system_err("receiveoops");
                return -1;
            }
            printf("childfin: %d %s %d\n", x, bfr, prio);
            break;
        default:
        x = mq_open("/lol", O_CREAT | O_RDWR, 0755, NULL);
        if (x == -1) {
            system_err("parentoops");
            return -1;
        }
        mq_getattr(x, &a);
        printf("flag:%ld\n\n", a.mq_flags);
        a.mq_flags = O_NONBLOCK;
        sleep(5);
        if (mq_setattr(x, &a, NULL)) {
            system_err("setattr");
        }
        mq_getattr(x, &a);
        printf("flag:%ld\n\n", a.mq_flags);
        printf("parentwait");
        fflush(stdout);
        wait(0);
        printf("parentfin");
    }
    return 0;
}

0 个答案:

没有答案