消息队列的创建和使用 ftok() msgget() msgsnd() msgrcv()

1、ftok(3)

#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);

功能:创建一个消息队列的key值,
参数:
pathname:路径名称(可写任意一个文件路径)
proj_id :可使用好数字(1~255)
返回值:
成功:返回一个根据参数产生的key值。
失败:-1
2、msgget(2)

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgget(key_t key, int msgflg);

功能:创建(或使用)一个消息队列。
参数:
key:由ftok()函数生成;
msgflg:一般设置为:CREAT|0644(即:创建一个本人可读写,其它人可读的消息队列。
返回值:
成功:返回一个正整数做为消息队列号;
失败:-1。

3、msgsnd(2)

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
struct msgbuf {
    
    
       long mtype;       /* 消息类型,正整数即可 */
       char mtext[256];    /* 需要发送数据的大小,可以填其它数值 */
} msgp;

功能:向消息队列里发送一个数据
参数:
msqid:msgget()函数的返回值;
msgp:填上面结构变量名称;
msgsz:消息的大小:sizeof(msgp)-sizeof(long)
msgflg:一般填IPC_NOWAIT。
返回值:
成功:0
失败:-1
4、msgrcv(2)

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp,
 int msgflg);
struct msgbuf {
    
    
       long mtype;       /* message type, must be > 0 */
       char mtext[1];    /* message data */
};

功能:从消息队列里读取一条数据。
参数:
msgtyp:一般填写0。
msgsz:数值应大于或等于发送者的大小,才能取出一条数据 ,一般和发送者一样大。
其它:参见msgsnd()函数的参数。
返回值:
成功:返回得到的字节数;
失败:-1

通过消息队列完成进程间异步通信(发送者)代码举例:

/*    ipc_send.c      
     功能:发消息队列里一次发送10条251字节的数据    
 */
#include <strings.h>
#include <string.h>
#include "rand_h.h"
#include "unistd.h"
#define PATHNAME_PIDA "pathname."   //定义路径宏
#define PROJ_ID         10          //定义编号宏
int main(void){
    
    
    key_t key_id;
    key_id = ftok(PATHNAME_PIDA,PROJ_ID);//创建一个消息队列key
    int msg_id;
    msg_id = msgget(key_id,IPC_CREAT|0664);//创建一个消息队列号
    struct msgbuf{
    
                 //定义一个消息队列内容结构体
        long mtype;
        char mtext[256];
    }msg_buf;
    bzero(&msg_buf.mtext,256);//清空数组里的内容
    msg_buf.mtype = 3;//设置消息队列类型
    int str_num =0;
    for(str_num = 0;str_num <10;str_num ++){
    
    
        strcpy(msg_buf.mtext,rand_str(250));//通过随机函数,产生一个250字节字符串复制结构体的数组里
        if(strlen(msg_buf.mtext)<256){
    
    //为数组加'\0'字符做了字符串结束标志
            msg_buf.mtext[strlen(msg_buf.mtext)] ='\0';
        }
        else{
    
    
            msg_buf.mtext[256] ='\0';
        }
        //向消息队列里发送数据。
        msgsnd(msg_id,(void *)&msg_buf,\
                        sizeof(msg_buf)-sizeof(long),IPC_NOWAIT);
        printf("%s\n",msg_buf.mtext);//显示发消息队列里发送数据的内容
        sleep(1);
    }
    return 0;
}
/*    rand_h.h
    功能:随机数生成头文件
*/
#ifndef     __RAND_H_H_          //头文件卫士框架
#define     __RAND_H_H_
char rand_func(void);
char *rand_str(int);
#endif
/*    rand_h.c
生成随机字符串
*/
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <strings.h>
#include "rand_h.h"
char rand_func(void){
    
    
    int func_num = rand() % 4;//产生0~3合计4种类型字符(大小写字母、数字、特殊字符
    int num = 0;  //保存生成的数字,用于转换为字符
    char ch='\0';//保存产生的随机字符
    int num_buf[5]={
    
    33,35,46,64,95};//特殊字符的ASCII码
    switch(func_num){
    
    
            case 0:
                num = rand() % 10+48;//生成0~9数字对应的ASCII码
                break;
            case 1:
                num = rand() %26 +97;//生成小写字母ASCII码
                break;
            case 2:
                num = rand() %26 + 65;//生成大小写线ASCII码
                break;
            case 3:
                num = num_buf[rand()%5];//生成特殊子符在数组里的下标并得到ASCII码
                break;
            default :
                break;
    }
    sprintf(&ch,"%c",num);//将数字转换成ASCII对应的字符
    return ch;//返回单次生成的字符
}
char *rand_str(int size){
    
    
    srand(time(NULL));//产生随机数种子
    char *str_p = malloc(size);//保存随机数的字符串地址。
    bzero(str_p,size);//清空字符串里的内容
    int buf_num = size;
    while(size != 0){
    
    //调用size次,产生的字符保存到字符串里
        str_p[buf_num-size] = rand_func();
        size--;
    }
    return str_p;//返回保存字符器的地址给调用者.
}

发送者编译执行如下(通过IPCS命令可以查看消息队列):

ipc$gcc rand_h.c ipc_send.c  -o send
ipc$./send
6O_8@5S10Nu9vJ!KOL1_C6QuF2o@tuv3_3ZU!3J1cq8dqsGxvjj!TY4tW0L_!RE!kW!_7X!FE#!7V9!2@#43.GM##65k2#k.@107.l_gP0Yk2x5R_._!H.m#xSvR4_j837Csac0P9z8#4h#f6UP#@bsraTHE.#7E.X14N#i4.187pV5jZ2mPMFOF6!35KB_ZV3!J4nL5t@RTS7_@dlrC3qLlh726U9@_Eh.h@A3x617.x4Xm_1HS841q!w
1X_nlKeRUpS3bVE823.z5brPbe7#TKz!fn0WxtTD#!08!.OVp1ufaHi.8!o@@t81@X_1e0L_M_G_5Upo7jR5#k80.fn#Pd8.f5CWg0292d_@s0#C41_uXBdRl!!vV!9D499#QPsu2LF01KqpN2Rmp292a!k#!CjxbXl0@nb!6hO#HJ8!tm1jwU!19oy5f@!@!_y.V1_vcyUJx2.4@m@VI@I1BO@!j4!S3!7c0_5C0Q31loNYPO#55jR!!_
.............

通过消息队列完成进程间异步通信(接收者)代码举例:

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <strings.h>
#include <string.h>
#define PATHNAME_PIDA "pathname."
#define PROJ_ID         10
int main(void){
    
    
    key_t key_id;
    key_id = ftok(PATHNAME_PIDA,PROJ_ID);
    int msg_id;
    msg_id = msgget(key_id,IPC_EXCL);
    struct msgbuf{
    
    
        long mtype;
        char mtext[256];
    }msg_buf;
    bzero(&msg_buf.mtext,256);
    msg_buf.mtype = 3;
    msgrcv(msg_id,&msg_buf,sizeof(msg_buf)-sizeof(long),0,IPC_NOWAIT);
    printf("%s\n",msg_buf.mtext);
    return 0;
}

接收者编译执行如下(通过IPCS命令可以查看消息队列):

ipc$gcc ipc_recv.c -o recv
ipc$./recv 
CG@5X!_.3RC_q.3Y_v32J8M.z_z#sn@.!LCUgJZxH@2!4A@@Zm.0Z_01d!aTGdW.k024.Q6@w@30V@A1C48416thspN..7446in56w.g@n2rF2wlws!!YCFBiB952daG66N4.Dd@v1o9o#79cn!8@@.K0H#I5R@QF30@K#jH4X_.N7_jnLn2#Wqlv23!4@O8Yd@@j_S!5_CSRpll_@6y666i.4O7!P.3tqM0K11@yHU02_t!!f_!t82D28
ipc$./recv 
3!P2P!T0#.QF!QHr7!HyQsj!S22E84am.z!MJSx7.0#7CyHJ#@lh1@ci37_Xgb!aYvm@E!O_oC5dzqUDS9F4L@!.#5#iu946Pr9gj!6v5J!_p1Q#kcL97.K!TRhEk1F!3G4mK0tZ05A10P##Nm@Z.ck.5@Dk@jcLoFYN!c6A8@o363K2Kh.O@N18_K#hf95.#_83B_3!X@1rHsSmk7P65#S._A@w01@cLuVsoBF54bzno4!1!X!0@!5Cu!
05ipc$vim ipc_recv.c 

猜你喜欢

转载自blog.csdn.net/weixin_47273317/article/details/105728070