UNIX IPC: POSIX 消息队列 与 信号

POSIX消息队列可以注册空队列有消息到达时所触发的信号,而信号触发对应的信号处理函数。

下面是一份基本的消息队列和信号处理结合的代码(修改自UNIX网络编程:进程间通信)

#include <stdio.h>

#include <stdlib.h>



#include <unistd.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <mqueue.h>

#include <signal.h>

#include <pthread.h>





mqd_t queue;

void* buff;

struct mq_attr attr;

struct sigevent sigev;



static void sig_user1(int signo) {

    printf("current pid:%d, threadid:%u\n", getpid(), pthread_self());

    int n, prio;

    /*     signal will be unregistered from previous registered message queue 

        when first message arrived.

        So register signal again if we want trigger the signal handler again */

    mq_notify(queue, &sigev);

    

    /* read msg */

    int res = mq_receive(queue, buff, attr.mq_msgsize, &prio);

    if (res < 0) {

        perror("receive msg fail");

        exit(-1);

    }

    printf("prio: %d, msg: %s\n", prio, (char*)buff);

    return;

}



int main(int argc, char** argv) {

    char* name = "/testmq";

    if (argc > 0) {

        name = argv[1];

    }



    queue = mq_open(name, O_RDONLY);



    if (queue < 0) {

        perror("open message queue fail");

        return -1;

    }



    int res = mq_getattr(queue, &attr);

    if (res != 0) {

        perror("get message queue fail");

        return -1;

    }



    buff = malloc(attr.mq_msgsize);



    signal(SIGUSR1, sig_user1);



    sigev.sigev_notify = SIGEV_SIGNAL;

    sigev.sigev_signo = SIGUSR1;



    mq_notify(queue, &sigev);



    printf("[%d.%d] start to waiting\n", getpid(), pthread_self());

    for (;;) {

        pause();

    }



    return 0;

}

 

运行输出:

hgf@ubuntu:~/ipc$ ./mqnotify /haha

[25328.1410565952] start to waiting

current pid:25328, threadid:1410565952

可以看到主线程和执行信号处理的线程是同一个,这估计也是书上说以上程序存在问题,因为有些函数调用不应该放在信号处理函数当中。因为它们可能使用了互斥资源可能造成死锁,比如printf,当其正在处理时又来一个信号于是再次调用printf然后可能上一个printf还没有释放对一些互斥资源的所有权造成死锁。

你可能感兴趣的:(unix)