[linux操作系统实验]消息的发送与接收(消息发送中英文都乱码/变长消息结构体/msgget()一直失败返回-1)

/ 2,020评论 / 13943阅读 / 6点赞

问题

msgget()一直失败返回-1

消息发送中英文都乱码

struct msg_s{
    long  mtype;       //消息类型
    char  mtext[1024]; //消息的文本
    //char* mtext;     //这样是错的!!
};

msg_send.cpp

#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <iostream>
#include <string>
#include <cstring>
#include <time.h>
#include <fstream>
using namespace std;

/*发送进程*/
struct msg_s
{
        long mtype;
        char* mtext;
};

int main()
{
        cout << "<< 我是进程1!" << endl;
        int msgqid = 0;
        //搞一个消息队列描述符
        while((msgqid = msgget(key_t(77), 0777 | IPC_CREAT)) == -1);
        msg_s* msgp = new msg_s();
        msgp->mtype = 2;
        msgp->mtext = new char[1024];
        cout << "指针大小:" << sizeof(int*) << endl;
        cout << "进程1:mtext内容地址: " << (int*)(msgp->mtext) << endl;
        memset(msgp->mtext, 0, 1024);
        memset(msgp->mtext, 48 + msgp->mtype - 1, 10);
        msgsnd(msgqid, msgp, 1024, 0);
        cout << "进程1 发送内容:" << msgp->mtext << endl;
        delete[]msgp;
        return 0;
}

msg_rev.cpp

#include <sys/types.h>
#include <sys/msg.h>
#include <signal.h>
#include <sys/ipc.h>
#include <iostream>
#include <cstring>
#include <fstream>
#include <unistd.h>
using namespace std;

/*接收进程*/
struct msg_s
{
        long mtype;
        char mtext[];
};

int main()
{
        cout << "进程2:我是进程2!" << endl;
        int msgqid = 0;
        //搞一个消息队列描述符
        while((msgqid = msgget(key_t(77), 0777 | IPC_CREAT)) == -1);
        msg_s* msgp =  (msg_s*)malloc(sizeof(long) + sizeof(char) * 1025);
        memset(msgp->mtext, 0, 1025);
        msgrcv(msgqid, msgp, 1024, 0, 0);
        cout << "int 大小:" << sizeof(int) << " | long 大小:" << sizeof(long) << endl;
        cout << "进程2:" << msgp->mtype - 1 << " | " << msgp->mtext << endl;
        cout << "mtext: " << (int*)(*((long*)(msgp->mtext))) << endl;
        msgctl(msgqid,IPC_RMID,0);
        return 0;
}

可变长度的消息结构体

如上所述,如果只能在结构体内定义数组,则消息的大小必须是固定的吗?

看这一小节的标题就知道显然不是的,我们可以使用柔性数组来实现变长消息结构体,使得mtext的内存空间即与结构体连续,又是可变长度。这实际上在上一小节的举例中msg_rev.cpp中已经用到了。

struct msg_s {
        long mtype;
        char mtext[];   //mtext必须放在最后
};
int main()
{
    //使用malloc动态申请空间
    msg_s* coolmsg = (msg_s*)malloc(sizeof(long) + sizeof(char) * 长度);
    //然后就可以初始化并使用它了
    coolmsg->mtype = 1;
    //将mtext的内容全部置为 'A'
    memset(coolmsg->mtext, 'A', 长度);
}

获取消息的信息

使用msgctl()可以获取到消息缓冲区地址,由此可以查询消息队列中消息数目,最后一个发送消息的进程的pid,发送时间,队列中的最大字节数等等。

struct  msqid_ds
{  
      struct  ipc_perm  msg_perm; /*许可权结构*/
      short  pad1[7];    /*由系统使用*/
      ushort msg_qnum;   /*队列上消息数*/
      ushort msg_qbytes; /*队列上最大字节数*/
      ushort msg_lspid;  /*最后发送消息的PID*/
      ushort msg_lrpid;  /*最后接收消息的PID*/
      time_t msg_stime;  /*最后发送消息的时间*/
      time_t msg_rtime;  /*最后接收消息的时间*/
      time_t msg_ctime;  /*最后更改时间*/
};
struct  ipc_perm
{  
      ushort uid;  /*当前用户*/
      ushort gid;  /*当前进程组*/
      ushort cuid; /*创建用户*/
      ushort cgid; /*创建进程组*/
      ushort mode; /*存取许可权*/
      { short pid1; long pad2;} /*由系统使用*/  
}
struct msg_s
{
        long mtype;
        char mtext[];
};

void tempfun()
{
    int msgqid = 0;
    //搞一个消息队列描述符
    while((msgqid = msgget(key_t(77), 0777 | IPC_CREAT)) == -1);
    //申请一个消息长度1025的消息
    msg_s* msgp =  (msg_s*)malloc(sizeof(long) + sizeof(char) * 1025);
    memset(msgp->mtext, 0, 1025);

    //接收一次信息
    msgrcv(msgqid, msgp, 1024, 0, 0);
    msqid_ds cool_msgDs;

    //查询缓冲区
    msgctl(msgqid, IPC_STAT, &cool_msgDs);
    //获取缓冲区中记录的最后发送消息的进程pid
    int send_pid = cool_msgDs.msg_lspid;
    cout << "已经最后一个发送消息的进程pid:" << send_pid << endl;
    return 0;
}

具体实验内容

实验内容

消息的创建、发送和接收。使用系统调用msgget( ),msgsnd( ),msgrev( ),及msgctl( )编制一长度为1k的消息发送和接收的程序

概念

消息(message)是一个格式化的可变长的信息单元。消息机制允许由一个进程给其它任意的进程发送一个消息。当一个进程收到多个消息时,可将它们排成一个消息队列。消息使用二种重要的数据结构:一是消息首部,其中记录了一些与消息有关的信息,如消息数据的字节数;二个消息队列头表,其每一表项是作为一个消息队列的消息头,记录了消息队列的有关信息。

涉及函数

msgget()

msgsnd()

msgrcv()

msgctl()

struct  msqid_ds
{  
      struct  ipc_perm  msg_perm;     /*许可权结构*/
      short  pad1[7];                 /*由系统使用*/
      ushort msg_qnum;                /*队列上消息数*/
      ushort msg_qbytes;              /*队列上最大字节数*/
      ushort msg_lspid;               /*最后发送消息的PID*/
      ushort msg_lrpid;               /*最后接收消息的PID*/
      time_t msg_stime;               /*最后发送消息的时间*/
      time_t msg_rtime;               /*最后接收消息的时间*/
      time_t msg_ctime;               /*最后更改时间*/
};
struct  ipc_perm
{  
      ushort uid;                     /*当前用户*/
      ushort gid;                     /*当前进程组*/
      ushort cuid;                    /*创建用户*/
      ushort cgid;                    /*创建进程组*/
      ushort mode;                    /*存取许可权*/
      { short pid1; long pad2;}       /*由系统使用*/  
}

源代码

msg_send.cpp

#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <iostream>
#include <string>
#include <cstring>
#include <time.h>
#include <fstream>
using namespace std;

/*发送进程*/
struct msg_s
{
        long mtype;
        char mtext[];
};

int main()
{
        cout << "<< 我是进程1!" << endl;
        int msgqid = 0;
        while((msgqid = msgget(key_t(77), 0777 | IPC_CREAT)) == -1);    //搞一个消息队列描述符

        msg_s* msgp = (msg_s*)malloc(sizeof(long) + sizeof(char) * 1025);
        msgp->mtype = 10;
        while(msgp->mtype > 0)
        {
                memset(msgp->mtext, 0, 1024);
                memset(msgp->mtext, 48 + msgp->mtype - 1, 10);
                msgsnd(msgqid, msgp, 1024, 0);
                cout << "进程1 :" << msgp->mtype - 1 << " | " << msgp->mtext << endl;
                --(msgp->mtype);
        }
        delete[]msgp;
        return 0;
}

msg_rev.cpp

#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <iostream>
#include <cstring>
#include <fstream>
#include <unistd.h>
using namespace std;

/*接收进程*/
struct msg_s
{
        long mtype;
        char mtext[1025];
        msg_s(long in_mtype)
        {
                mtype = in_mtype;
        }
};

int main()
{
        cout << "<<  我是进程2!" << endl;
        int msgqid = 0;
        while((msgqid = msgget(key_t(77), 0777 | IPC_CREAT)) == -1);  //搞一个消息队列描述符

        cout << "<< 进程2开始等待接收消息..."<<endl;
        msg_s* msgp = new msg_s(10);
        do{
                memset(msgp->mtext, 0, 1025);
                msgrcv(msgqid, msgp, 1024, 0, 0);
                cout << "<< 进程2:" << msgp->mtype - 1 << " | " << msgp->mtext << endl;
        }while(msgp->mtype > 1);

        msgctl(msgqid,IPC_RMID,0);
        return 0;
}

运行结果截图

思考

msg_send.cpp

#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <iostream>
#include <string>
#include <cstring>
#include <time.h>
#include <fstream>
#include <signal.h>
#include <unistd.h>
using namespace std;

/*发送进程*/
struct msg_s
{
        long mtype;
        char mtext[];
};

/*指示是否接收*/
bool is_rev = false;

void setRev(int)
{
        is_rev = true;
}
int main()
{
        if(fork() == 0)
        {
                execl("./msg_rev", "msg_rev",NULL);
        }else{
                cout << "<< 我是进程1!" << endl;
                int msgqid = 0;
//搞一个消息队列描述符
                while((msgqid = msgget(key_t(77), 0777 | IPC_CREAT)) == -1);    
                signal(16, setRev);
                msg_s* msgp = (msg_s*)malloc(sizeof(long) + sizeof(char) * 1025);
                msgp->mtype = 10;
                (msgp->mtext)[0] =  'a';
                msgsnd(msgqid, msgp, 1, 0);
                cout << "<< 进程1:等待进程2连接..." << endl;
                msgp->mtype = 10;
                while(msgp->mtype > 0)
                {
                        while(is_rev == false)
                                usleep(1000 * 100);
                        is_rev = false;
                        memset(msgp->mtext, 0, 1024);
                        memset(msgp->mtext, 48 + msgp->mtype - 1, 10);
                        msgsnd(msgqid, msgp, 1024, 0);
                        cout << "<< 进程1 :" << msgp->mtype - 1 << " | " << msgp->mtext << endl;
                        --(msgp->mtype);
                cout << "<< 进程1:发送结束" << endl;
                delete[]msgp;
        }
        return 0;
}

msg_rev.cpp

#include <sys/types.h>
#include <sys/msg.h>
#include <signal.h>
#include <sys/ipc.h>
#include <iostream>
#include <cstring>
#include <fstream>
#include <unistd.h>
using namespace std;

/*接收进程*/
struct msg_s
{
        long mtype;
        char mtext[];
};

int main()
{
        cout << "进程2:我是进程2!" << endl;
        int msgqid = 0;
//搞一个消息队列描述符
        while((msgqid = msgget(key_t(77), 0777 | IPC_CREAT)) == -1);  
        msg_s* msgp =  (msg_s*)malloc(sizeof(long) + sizeof(char) * 1025);
        cout << "进程2:正在等待进程1连接" << endl;
        int send_pid = 0;
        memset(msgp->mtext, 0, 1025);
        msgrcv(msgqid, msgp, 1024, 0, 0);
        msqid_ds cool_msgDs;
        msgctl(msgqid, IPC_STAT, &cool_msgDs);
        send_pid = cool_msgDs.msg_lspid;
        cout << "进程2:已经获取到进程1的pid:" << send_pid << endl;
        kill(send_pid, 16);
        cout << "进程2:开始等待接收消息..."<<endl;
        do{
                memset(msgp->mtext, 0, 1025);
                msgrcv(msgqid, msgp, 1024, 0, 0);
                cout << "进程2:" << msgp->mtype - 1 << " | " << msgp->mtext << endl;
                kill(send_pid, 16);
        }while(msgp->mtype > 1);

        msgctl(msgqid,IPC_RMID,0);
        return 0;
}
  1. Armandosed说道:

    https://edpill.top/# ed pills online

  2. HarveyBeemi说道:

    https://edpill.top/# where to buy ed pills

  3. Armandosed说道:

    http://medicationnoprescription.pro/# canada pharmacy without prescription

  4. MatthewDoolo说道:

    ed meds cheap: boner pills online – cheap erection pills

  5. PhilipBup说道:

    online pharmacy without prescription uk pharmacy no prescription pharmacy without prescription

  6. Armandosed说道:

    https://medicationnoprescription.pro/# online pharmacies without prescription

  7. HarveyBeemi说道:

    https://onlinepharmacyworld.shop/# drugstore com online pharmacy prescription drugs

  8. Armandosed说道:

    http://edpill.top/# cheap erection pills

  9. PhilipBup说道:

    best canadian pharmacy no prescription pharmacy discount coupons canadian pharmacy without prescription

  10. AustinWhoto说道:

    medication online without prescription: canada prescription online – meds online without prescription

  11. MatthewDoolo说道:

    best no prescription pharmacy: online canadian pharmacy coupon – best online pharmacy no prescription

  12. Armandosed说道:

    https://medicationnoprescription.pro/# best online pharmacy without prescriptions

  13. HarveyBox说道:

    https://edpill.top/# buy erectile dysfunction pills online

  14. PhilipBup说道:

    ed online prescription cost of ed meds buy erectile dysfunction treatment

  15. Armandosed说道:

    http://medicationnoprescription.pro/# prescription online canada

  16. HarveyBeemi说道:

    http://edpill.top/# erectile dysfunction meds online

  17. MatthewDoolo说道:

    buy ed meds: cost of ed meds – affordable ed medication

  18. Armandosed说道:

    https://edpill.top/# buy erectile dysfunction medication

  19. PhilipBup说道:

    ed meds on line cheap ed medication how to get ed meds online

  20. MatthewDoolo说道:

    canadian pharmacies not requiring prescription: canadian pharmacy no prescription – best canadian pharmacy no prescription

  21. Armandosed说道:

    https://edpill.top/# online ed pharmacy

  22. HarveyBeemi说道:

    https://edpill.top/# cheap ed drugs

  23. Josephtrink说道:

    http://amoxicillina.top/# order amoxicillin online

  24. BrainSaw说道:

    https://azithromycina.pro/# zithromax 500 price

  25. JamesLot说道:

    20 mg prednisone prednisone 20 mg tablets coupon prednisone acetate

  26. MichaelPycle说道:

    prednisone brand name in india: can i order prednisone – purchase prednisone no prescription

  27. MichaelPycle说道:

    generic name for ivermectin: stromectol tablets – stromectol price us

  28. BrainSaw说道:

    https://azithromycina.pro/# can you buy zithromax over the counter in mexico

  29. JamesLot说道:

    ivermectin 2ml ivermectin 12 stromectol liquid

  30. BryanSturf说道:

    clomid cheap: where can i buy cheap clomid without prescription – how can i get clomid without a prescription

  31. MichaelPycle说道:

    stromectol 3mg tablets: where to buy ivermectin – buy stromectol uk

  32. BrainSaw说道:

    http://prednisonea.store/# prednisone 1 mg for sale

  33. MichaelPycle说道:

    ivermectin over the counter uk: ivermectin 3mg tablets – ivermectin over the counter uk

  34. JamesLot说道:

    stromectol cvs ivermectin 3mg tab stromectol over the counter

  35. DomenicDobby说道:

    amoxicillin 500 mg: cost of amoxicillin – amoxicillin for sale online

  36. MichaelPycle说道:

    where can i buy amoxicillin without prec: can you buy amoxicillin over the counter in canada – order amoxicillin online

  37. BrainSaw说道:

    https://clomida.pro/# get cheap clomid price

  38. Josephtrink说道:

    https://prednisonea.store/# over the counter prednisone medicine

  39. BryanSturf说道:

    where to buy cheap clomid tablets: where can i get generic clomid no prescription – where can i buy clomid prices

  40. JamesLot说道:

    cost generic clomid without insurance where buy cheap clomid without rx where can i get clomid without rx

  41. MichaelPycle说道:

    can i get generic clomid pills: can i buy clomid prices – where to buy generic clomid without a prescription

  42. MichaelPycle说道:

    zithromax for sale online: zithromax online usa no prescription – zithromax 250 price

  43. BryanSturf说道:

    get cheap clomid without insurance: get cheap clomid no prescription – how can i get clomid without insurance

  44. Williamzew说道:

    buy cipro cheap: ciprofloxacin mail online – ciprofloxacin 500mg buy online

  45. JeromedUb说道:

    odering doxycycline buy cheap doxycycline online doxycycline order online

  46. RussellVeila说道:

    tamoxifen and osteoporosis: tamoxifen citrate – should i take tamoxifen

  47. RussellVeila说道:

    doxycycline 100mg capsules: doxycycline monohydrate – buy doxycycline monohydrate

  48. JeromedUb说道:

    where to buy diflucan online how much is a diflucan pill over the counter diflucan pill

  49. Williamzew说道:

    ciprofloxacin generic: ciprofloxacin mail online – buy cipro cheap

  50. RussellVeila说道:

    cytotec abortion pill: cytotec pills buy online – buy cytotec online fast delivery

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注