c++linuxipcsysvsysv-ipc

linux ipc. Why is msgrcv always blocking?


client readline write to shared memory.and send a msg to server. server get msg and read from shared memrory.

But the server cannot output correctly, The server did not output anything,I do not know why.

the man pages says that: If no message of the requested type is available and IPC_NOWAIT isn't specified in msgflg, the calling process is blocked until one of the following conditions occurs

but the server is always blocked.

I use gdb to debug it,find out that std::cout does not work

debug context

Breakpoint 1, main () at shared_mem_server.cpp:35
35      sem_init(reinterpret_cast<sem_t*>(shm),0,1);
(gdb) p shm
$1 = 0x7ffff7ff6000 ""
(gdb) x/10w 0x7ffff7ff6000
0x7ffff7ff6000: 0   0   0   0
0x7ffff7ff6010: 0   0   0   0
0x7ffff7ff6020: 0   0
(gdb) s
__new_sem_init (sem=0x7ffff7ff6000, pshared=0, value=1) at sem_init.c:31
31  sem_init.c: No such file or directory.
(gdb) return
Make __new_sem_init return now? (y or n) n
Not confirmed
(gdb) finish
Run till exit from #0  __new_sem_init (sem=0x7ffff7ff6000, pshared=0, value=1)
    at sem_init.c:31
main () at shared_mem_server.cpp:37
37          msgrcv(msgid,&msg,256,ret_type,0);
Value returned is $2 = 0
(gdb) x/10w 0x7ffff7ff6000
0x7ffff7ff6000: 1   0   0   0
0x7ffff7ff6010: 0   0   0   0
0x7ffff7ff6020: 0   0
(gdb) p sem_sz
$3 = 32
(gdb) n
38          sem_p(reinterpret_cast<sem_t*>(shm));
(gdb) n
39          if(shm + sem_sz == "q")
(gdb) x/10w 0x7ffff7ff6000
0x7ffff7ff6000: 0   0   0   0
0x7ffff7ff6010: 0   0   0   0
0x7ffff7ff6020: 3355185 0
(gdb) x/12w 0x7ffff7ff6000
0x7ffff7ff6000: 0   0   0   0
0x7ffff7ff6010: 0   0   0   0
0x7ffff7ff6020: 3355185 0   0   0
(gdb) n
41          std::cout << "shared memory " << shm + sem_sz;
(gdb) n
42          sem_v(reinterpret_cast<sem_t*>(shm));
(gdb) q

Below is the code

server code:

#include <iostream>
#include <sys/shm.h>
#include <sys/msg.h>

#include "error.h"
#include "sempv.h"

const int SHM_SIZE=1024;

struct msg_form{
    long  msg_type;
    char msg_text[256];
};

int main(){
    key_t key;
    int shmid,msgid,ret_type = 888,sem_sz = sizeof(sem_t);
    char *shm;
    

    msg_form msg;

    if((key = ftok(".",'v')) < 0)
        unix_error("ftok error");
    
    if((shmid = shmget(key,SHM_SIZE,IPC_CREAT|0666)) == -1)
        unix_error("create shared memory error");

    if((shm = (char*)shmat(shmid,0,0)) == (void*)-1){
        unix_error("attach shared memeory error");
    }
    if((msgid = msgget(key,IPC_CREAT|07777)) == -1)
        unix_error("msgget error");
    sem_init(reinterpret_cast<sem_t*>(shm),0,1);
    while(true){
        msgrcv(msgid,&msg,256,ret_type,0);
        sem_p(reinterpret_cast<sem_t*>(shm));
        if(shm + sem_sz == "q")
            break;
        std::cout << "shared memory " << shm + sem_sz;
        sem_v(reinterpret_cast<sem_t*>(shm));
    }
    shmdt(shm);
   
    shmctl(shmid,IPC_RMID,0);
    shmctl(msgid,IPC_RMID,0);
    return 0;
}


client code

#include <iostream>
#include <sys/shm.h>
#include <sys/msg.h>

#include "error.h"
#include "sempv.h"
#include <string>

using std::string;

const int SHM_SIZE=1024;

struct msg_form{
    long  msg_type;
    char msg_text[256];
};

int main(){
    key_t key;
    int shmid,msgid,sem_sz = sizeof(sem_t);
    char *shm;
    
    int err;

    msg_form msg;
    string s;

    if((key = ftok(".",'v')) < 0)
        unix_error("ftok error");
    
    if((shmid = shmget(key,SHM_SIZE,0)) == -1)
        unix_error("shmget error");
    if((shm = (char*)shmat(shmid,0,0)) == (void*)-1){
        unix_error("attach shared memeory error");
    }
    if((msgid = msgget(key,0777)) == -1)
        unix_error("msgget error");
    std::cout << "key is " << key << std::endl;
    
    while(getline(std::cin,s)){
        sem_p(reinterpret_cast<sem_t*>(shm));
        memset(shm+sem_sz,0,SHM_SIZE-sem_sz);
        memcpy(shm+sem_sz,s.c_str(),s.size());
       
        msg.msg_type = 888;
        sprintf(msg.msg_text,"shared memory write signal");

        if((err =  msgsnd(msgid,&msg,sizeof(msg.msg_text),0)) == -1)
            unix_error("msgsnd error");
         sem_v(reinterpret_cast<sem_t*>(shm));
        //std::cout << "message send\n";
    }
    return 0;
}

Solution

  • General remarks:

    In the server:

    In the client:

    Here is the C version of your modified code:

    Server:

    #include <stdio.h>
    #include <sys/shm.h>
    #include <sys/msg.h>
    #include <stdlib.h>
    #include <semaphore.h>
    
    
    const int SHM_SIZE=1024;
    
    struct msg_form{
        long  msg_type;
        char msg_text[256];
    };
    
    
    static void unix_error(const char *str)
    {
    
      fprintf(stderr, "%s\n", str);
    
      exit(1);
    }
    
    
    int main(){
        key_t key;
        int shmid,msgid,ret_type = 888,sem_sz = sizeof(sem_t);
        char *shm;
        
    
        struct msg_form msg;
    
        if((key = ftok(".",'v')) < 0)
            unix_error("ftok error");
        
        if((shmid = shmget(key,SHM_SIZE,IPC_CREAT|0666)) == -1)
            unix_error("create shared memory error");
    
        if((shm = (char *)shmat(shmid,0,0)) == (void*)-1){
            unix_error("attach shared memory error");
        }
        if((msgid = msgget(key,IPC_CREAT|07777)) == -1)
            unix_error("msgget error");
        sem_init((sem_t *)(shm),1,1);
        while(1){
            msgrcv(msgid,&msg,256,ret_type,0);
            sem_wait((sem_t *)(shm));
            if (*(shm + sem_sz) == 'q' && *(shm + sem_sz + 1) == '\n') {
                sem_post((sem_t *)(shm));
                break;
            }
            printf("shared memory: %s", shm + sem_sz);
            sem_post((sem_t *)(shm));
        }
        shmdt(shm);
       
        shmctl(shmid,IPC_RMID,0);
        msgctl(msgid,IPC_RMID,0);
        return 0;
    }
    

    Client:

    #include <stdio.h>
    #include <sys/shm.h>
    #include <sys/msg.h>
    #include <stdlib.h>
    #include <semaphore.h>
    #include <string.h>
    
    
    const int SHM_SIZE=1024;
    
    struct msg_form{
        long  msg_type;
        char msg_text[256];
    };
    
    
    static void unix_error(const char *str)
    {
    
      fprintf(stderr, "%s\n", str);
    
      exit(1);
    }
    
    
    int main(){
        key_t key;
        int shmid,msgid,sem_sz = sizeof(sem_t);
        char *shm;
        
        int err;
    
        struct msg_form msg;
        char s[256];
    
        if((key = ftok(".",'v')) < 0)
            unix_error("ftok error");
        
        if((shmid = shmget(key,SHM_SIZE,0)) == -1)
            unix_error("shmget error");
        if((shm = (char*)shmat(shmid,0,0)) == (void*)-1){
            unix_error("attach shared memeory error");
        }
        if((msgid = msgget(key,0777)) == -1)
            unix_error("msgget error");
        printf("key is 0x%x\n", (int)key);
        
        while(fgets(s, sizeof(s) - 1, stdin)) {
            sem_wait((sem_t *)(shm));
            memset(shm+sem_sz,0,SHM_SIZE-sem_sz);
            memcpy(shm+sem_sz,s, strlen(s));
           
            msg.msg_type = 888;
            snprintf(msg.msg_text, 256, "shared memory write signal");
    
            if((err =  msgsnd(msgid,&msg,sizeof(msg.msg_text),0)) == -1) {
                sem_post((sem_t *)(shm));
                unix_error("msgsnd error");
            }
            sem_post((sem_t *)(shm));
        }
        return 0;
    }