c - 帮助:wrong behavior code:client-server IPC signal handling on POSIX Message Queue UNIX C programming

标签 c posix ipc message-queue signals

在单个 main() 函数中,因此需要信号处理。使用Posix消息队列IPC机制,可以忽略优先级和其他链表消息,实现场景:

客户端:敲敲

服务器:谁在那儿

客户:pilcrow

服务器:pilcrow,非常感谢。

客户端:退出

所有进程终止

stdin->POSIX MsgQ 客户端发送“knock Knock”到服务器->服务器比较字符串并将“who's there”发送回客户端

我得到的是:

客户端:敲敲

服务器:谁在那里?

客户:pilcrow

枕头

客户端:退出

退出

第一轮成功地给了我正确的结果。从第二轮开始,客户端在控制台上输出相同的输入。

请帮忙。请记住使用 gcc -lrt 链接 mq_function。

下面是我的代码,

#include <mqueue.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#define MSG_SIZE 100  //max size of msg
#define MAX_MSG 1  //max # of msg
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
volatile sig_atomic_t mqflag; /* set nonzero by signal handler */
static void sig_usr1(int);
sigset_t zeromask, newmask, oldmask;

int  main(int argc, char **argv) {
int c,flags;/* for getopt() */
pid_t child_pid;
mqd_t msgq_id;
struct mq_attr attr;
struct sigevent sigev;
char *buff_forward,*buff_backward;
flags=O_RDWR | O_CREAT;
attr.mq_msgsize=MSG_SIZE;
attr.mq_maxmsg=MAX_MSG;
buff_forward=malloc(attr.mq_msgsize);
buff_backward=malloc(attr.mq_msgsize);

while ((c= getopt(argc, argv, "e")) != -1) {
    switch (c) {
       case 'e':   /* create the queue exclusive */
           flags|= O_EXCL;
           break;
    }
}

if (optind!=argc-1){
    printf("usage: [-e] <name>");
    exit(1);
}

msgq_id = mq_open(argv[optind],flags,FILE_MODE,&attr);
/* producing the message */
mq_getattr(msgq_id, &attr) ;
printf("Queue \"%s\":\n\t- stores at most %ld messages\n\t- "
        "large at most %ld bytes each\n\t- currently holds %ld messages\n",
        argv[optind], attr.mq_maxmsg, attr.mq_msgsize, attr.mq_curmsgs);

sigemptyset(&zeromask); /* no signals blocked */
sigemptyset(&newmask);
sigemptyset(&oldmask);
sigaddset(&newmask, SIGUSR1);
/* establish signal handler, enable notification */
signal(SIGUSR1, sig_usr1);
sigev.sigev_notify = SIGEV_SIGNAL;
sigev.sigev_signo = SIGUSR1;
sigprocmask(SIG_BLOCK, &newmask, &oldmask);/* block SIGUSR1 */

if ((child_pid=fork())==0){
    for (; ; ) {
        while (mqflag == 0)
            sigsuspend(&zeromask);
        mqflag =0; /* reset flag */
        msgq_id=mq_open(argv[optind],O_RDONLY);
        mq_receive(msgq_id, buff_forward, attr.mq_msgsize, NULL);
        mq_close(msgq_id);

        if (strcasecmp ("Knock Knock",buff_forward)==0){
             strcpy(buff_backward,"Server:Who's there?");
        }
        else if(strcasecmp ("pilcrow", buff_forward)==0){
             strcpy(buff_backward,"Server:Pilcrow,thanks a lot!");
        }
        else if(strcasecmp ("Exit",buff_forward)==0){
             kill(getppid(),SIGTERM);
             exit(0);
        }

    msgq_id=mq_open(argv[optind],O_WRONLY);
    mq_send(msgq_id,buff_backward,MSG_SIZE,NULL);
    mq_close(msgq_id);
        mq_notify(msgq_id, &sigev); /* reregister */
    }
    sigprocmask(SIG_UNBLOCK, &newmask, NULL); /* unblock SIGUSR1 */
    exit(0);
}
else if(child_pid>0){
    for(;;){
        printf("client:");
        gets(buff_forward);
        msgq_id=mq_open(argv[optind],O_WRONLY);
        mq_send(msgq_id,buff_forward,MSG_SIZE,NULL);
        mq_close(msgq_id);
        mq_notify(msgq_id, &sigev);
        while(mqflag==0)
            sigsuspend(&zeromask);
        mqflag==0;
        msgq_id=mq_open(argv[optind],O_RDONLY);
        mq_receive(msgq_id, buff_backward, attr.mq_msgsize, NULL);
        printf("%s\n",buff_backward);
        mq_close(msgq_id);
        }
    sigprocmask(SIG_UNBLOCK, &newmask, NULL); /* unblock SIGUSR1 */
    exit(0);
    }
return (EXIT_SUCCESS);
}
static void sig_usr1(int signo) {
    mqflag = 1;
    sigprocmask(SIG_BLOCK, &newmask, &oldmask);
    return;
}

最佳答案

子进程在调用 mq_notify 之前调用 sigsuspend (因为 mq_flag 隐式初始化为零,并且检查在通知之前中断被不当执行)。它永远无法按预期被唤醒。

mq_flag 初始化为 1 以查看差异。然后重构。

已更新

OP大大改变了代码,所以我也改变了这个答案。

关于c - 帮助:wrong behavior code:client-server IPC signal handling on POSIX Message Queue UNIX C programming,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6352765/

相关文章:

linux - 信号如何中断系统调用

c - 我该如何解决这个递归溢出?

c - 反编译一个gch文件

c++ - 为什么我需要从主线程使用 `pthread_exit()`,而它不是由 `pthread_create` 创建的?

c - 在多个进程之间共享 POSIX 信号量

Windows 命名管道访问控制

c++ - C++ 异常和 setjmp/longjmp 的代价

数组中的矛盾指针

c - 套接字 :client waiting even after recieving last byte

c++ - Boost.Interprocess 是否牺牲性能来实现可移植性