ftok

通过文件路径 pathname 以及 proj_id 获得键值key(键值:消息队列的标识),只要文件路径和proj_id不变,key值就不变

头文件:
    #include <sys/types.h>
    #include <sys/ipc.h>
原型:
    key_t ftok(const char *pathname, int proj_id);
参数:
    char *pathname:文件路径(目录文件或是普通文件);
    int proj_id:非0参数,用户自定义;
返回值:
    成功,返回key值;
    失败,返回-1,更新errno;
例程:
    key_t key = ftok("./", 'a');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }
    printf("key = %x\n", key);

msgget

创建或打开消息队列对象

头文件:
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
原型:
    int msgget(key_t key, int msgflg);
参数:
    key_t key:键值,提前约定或ftok函数创建获得;
    int shmflg:设置消息队列的访问权限,参数如下:
    IPC_CREAT:若消息队列对象不存在则创建,否则打开已经存在的消息队列对象;
    IPC_EXCL:只有消息队列对象不存在的时候才会创建,已存在则返回错误;
    IPC_NOWAIT:(非阻塞)如果本操作需要等待,则直接返回错误;
            IPC_CREAT|0666:如果内核中不存在与key值相同的消息队列,则创建消息队列,并设置8进制权限(按位或)。如果存在,则直接返回消息队列标识符msqid;
返回值:
    成功,返回消息队列标识 msqid;
    失败,返回-1,更新errno;
例程:
    int msqid = msgget(key, IPC_CREAT|0777);
    if(msqid < 0)
    {
        perror("msgget");
        return -1;
    }
    printf("msqid = %d\n", msqid);

msgsnd

向消息队列中发送数据

头文件:
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
原型:
    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
    int msqid:消息队列id;
    void *msgp:要发送的数据包,指向msgbuf的结构体指针,通用格式如下:
        struct msgbuf {
            long mtype;       /* message type, must be > 0 */消息类型,必须大于0,接收进程根据此数值来匹配想要的数据;
            char mtext[1];    /* message data */消息数据;
        };
    size_t msgsz:消息的大小,以字节为单位,即char mtext[1]的大小;
    int msgflg:发送方式:
        0:阻塞方式发送,如果消息队列满了,该函数阻塞;
        IPC_NOWAIT:非阻塞方式发送,如果消息队列满了,则该函数不会阻塞,立即返回,并且更新errno == EAGAIN;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
例程:
#define N 128
struct msgbuf
{
    long mtype;
    char mtext[N];
};
int main(void){
    struct msgbuf snd;
    snd.mtype = 100;//接收进程根据此数值来匹配队列中想要的数据
    if(msgsnd(msqid, &snd, N, 0) < 0)
    {
        perror("msgsnd");
        return -1;
    }
    printf("发送成功\n");
}

msgrcy

从消息队列中接收数据

头文件:
    #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);
参数:
    int msqid:消息队列id;
    void *msgp:存储获取到的数据包,这个消息包的类型必须与想要接收的消息数据类型一致;
        struct msgbuf {
            long mtype;       /* message type, must be > 0 */消息类型,必须大于0;
            char mtext[1];    /* message data */消息;
        };
    size_t msgsz:读取的数据大小,以字节为单位,即char mtext[1]的大小;
    long msgtyp:想要接收的消息类型:
        msgtyp == 0;     读取消息队列中的第一个消息,遵循先进先出的原则;
        msgtyp > 0;     读取消息队列中的第一个 msgtyp == mtype的消息;
        msgtyp < 0;     读取消息队列中消息类型(mtype <= |msgtyp|)中类型值最小的第一个消息;
    int msgflg:读取方式:
        0:阻塞方式读取,如果消息队列中没有期望的数据,则该函数阻塞;
        IPC_NOWAIT:非阻塞方式接收,如果消息队列中没有期望的数据,则函数不会阻塞,立即返回,并且更新errno == ENOMSG;
返回值:
    成功,返回实际读取数据的字节数,大于0;
    失败,返回-1;更新errno;
例程:
#define N 128
struct msgbuf
{
    long mtype;
    char mtext[N];
};
int main(void){
    struct msgbuf rcv;
    if(msgrcv(msqid, &rcv, N, 100, 0) < 0)
    {
        perror("msgrcv");
        return -1;
    }
    printf("接收到了:%s\n", rcv.mtext);
}

msgctl

消息队列的操控

头文件:
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
原型:
    int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
    int msqid:消息队列id;
    int cmd:控制方式;
        IPC_RMID:删除消息队列,第三个参数,填NULL;
        IPC_STAT:获取消息队列对象的内核结构体值,存放在第三个参数中;
        IPC_SET:设置消息队列对象的内核结构体值;
    struct msqid_ds *buf:指向msqid_ds结构的指针;
返回值:
    成功,返回0;
    失败,返回-1,更新errno;
例程:
    if(msgctl(msqid, IPC_RMID, NULL) < 0)
    {
        perror("msgctl");
        return -1;
    }

应用例程1

通过消息队列实现,对讲机版本的进程对话;A发送给B,然后B发给A,然后A发给B

A进程

#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>

#define N 128
#define SND 100
#define RCV 101

struct msgbuf
{
    long mtype;
    char mtext[N];
};

int main(int argc, const char *argv[])
{
    //key
    key_t key = ftok("./", 'b');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }
    printf("key = %x\n", key);
    //创建消息队列
    int msqid = msgget(key, IPC_CREAT|0777);
    if(msqid < 0)
    {
        perror("msgget");
        return -1;
    }
    printf("msqid = %d\n", msqid);
    //发送和接收数据包
    struct msgbuf snd;
    snd.mtype = SND;
    struct msgbuf rcv;
    while(1)
    {
        //发送数据
        bzero(snd.mtext, N);
        printf("请输入>>>");
        fgets(snd.mtext, N, stdin);
        if(msgsnd(msqid, &snd, N, 0)<0)
        {
            perror("msgsnd");
            return -1;
        }
        if(strncasecmp(snd.mtext, "quit", 4) == 0)
        {
            break;
        }  
        //接收数据
        bzero(rcv.mtext, N);
        if(msgrcv(msqid, &rcv, N, RCV, 0)<0)
        {
            perror("msgrcv");
            return -1;
        }
        printf("对方说:%s\n", rcv.mtext);
        if(strncasecmp(rcv.mtext, "quit", 4) == 0)
        {  
            //删除消息队列
            msgctl(msqid, IPC_RMID, NULL);
            break;  
        } 
    }
    return 0;
}

B进程

#include <stdio.h>
#include <sys/types.h>
#include <sys/msg.h>
#include <sys/ipc.h>
#include <string.h>

#define N 128
#define RCV 100
#define SND 101

struct msgbuf
{
    long mtype;
    char mtext[N];
};

int main(int argc, const char *argv[])
{
    //key
    key_t key = ftok("./", 'b');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }
    printf("key = %x\n", key);
    //创建消息队列
    int msqid = msgget(key, IPC_CREAT|0777);
    if(msqid < 0)
    {
        perror("msgget");
        return -1;
    }
    printf("msqid = %d\n", msqid);
    //接收和发送数据包
    struct msgbuf rcv;
    struct msgbuf snd;
    snd.mtype = SND;
    while(1)
    {
        //接收数据
        bzero(rcv.mtext, N);
        if(msgrcv(msqid, &rcv, N, RCV, 0)<0)
        {
            perror("msgrcv");
            return -1;
        }
        printf("对方说:%s\n", rcv.mtext);
        if(strncasecmp(rcv.mtext, "quit", 4) == 0)
        {
            //删除消息队列
            msgctl(msqid, IPC_RMID, NULL);
            break;
        }
        //发送数据
        bzero(snd.mtext, N); 
        printf("请输入>>>");
        fgets(snd.mtext, N, stdin);
        if(msgsnd(msqid, &snd, N, 0)<0)
        {   
            perror("msgsnd");
            return -1;  
        }
        if(strncasecmp(snd.mtext, "quit", 4) == 0)
        {
            break;
        }
    }
    return 0;
}

应用例程2

通过消息队列实现,打电话版本的进程对话;AB进程可以随时发送,随时接收

A进程

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#define N 128
struct msgbuf{
    long mtype;
    char mtext[N];
};
int flag = 0;
void *handler(void *arg)
{
    struct msgbuf rcvbuf;
    while(1)
    {
        if(msgrcv(*(int*)arg,&rcvbuf,N,2,0) < 0)
        {
            perror("msgrcv");
            break;
        }
        printf("B say:%s\n",rcvbuf.mtext);
        if(strncasecmp(rcvbuf.mtext,"quit",4) == 0)
        {
            flag = 1;
            break;
        }
    }
    pthread_exit(NULL);
}
void *handler_quit(void* arg)
{
    while(1)
    {
        if(flag)
        {
            printf("exit progress\n");
            exit(1);
        }
    }
    pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
    key_t key = ftok("./",'a');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }
    int msqid = msgget(key,IPC_CREAT|0664);
    if(msqid < 0)
    {
        perror("msgget");
        return -1;
    }
    pthread_t tid,tid_quit;
    if(pthread_create(&tid,NULL,handler,(void*)&msqid) != 0)
    {
        perror("pthread_create");
        return -1;
    }
    if(pthread_create(&tid_quit,NULL,handler_quit,NULL) != 0)
    {
        perror("pthread_create");
        return -1;
    }
    struct msgbuf sndbuf;
    sndbuf.mtype = 1;
    while(1)
    {
        bzero(sndbuf.mtext,sizeof(sndbuf.mtext));
        //printf("please input message-->");
        fgets(sndbuf.mtext,N,stdin);
        if(msgsnd(msqid,&sndbuf,N,0) < 0)
        {
            perror("msgsnd");
            return -1;
        }
        printf("sending successful\n");
        if(strncasecmp(sndbuf.mtext,"quit",4) == 0)
        {
            flag = 1;
            break;
        }
    }
    pthread_join(tid,NULL);
    pthread_join(tid_quit,NULL);
    return 0;
}

B进程

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#define N 128
struct msgbuf{
    long mtype;
    char mtext[N];
};
int flag = 0;
void *handler(void *arg)
{
    struct msgbuf rcvbuf;
    while(1)
    {
        if(msgrcv(*(int *)arg,&rcvbuf,N,1,0) < 0)
        {
            perror("msgrcv");
            break;
        }
        printf("A say:%s\n",rcvbuf.mtext);
        if(strncasecmp(rcvbuf.mtext,"quit",4) == 0)
        {
            flag = 1;
            break;
        }
    }
    pthread_exit(NULL);
}
void* handler_quit(void* arg)
{
    while(1)
    {
        if(flag)
        {
            printf("exit progress\n");
            exit(1);
        }
    }
    pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
    key_t key = ftok("./",'a');
    if(key < 0)
    {
        perror("ftok");
        return -1;
    }
    int msqid = msgget(key,IPC_CREAT|0664);
    if(msqid < 0)
    {
        perror("msgget");
        return -1;
    }
    pthread_t tid,tid_quit;
    if(pthread_create(&tid,NULL,handler,(void*)&msqid) != 0)
    {
        perror("pthread_create");
        return -1;
    }
    if(pthread_create(&tid_quit,NULL,handler_quit,NULL) != 0)
    {
        perror("pthread_create");
        return -1;
    }
    struct msgbuf sndbuf;
    sndbuf.mtype = 2;
    while(1)
    {
        bzero(sndbuf.mtext,sizeof(sndbuf.mtext));
        //printf("please input message-->");
        fgets(sndbuf.mtext,N,stdin);
        if(msgsnd(msqid,&sndbuf,N,0) < 0)
        {
            perror("msgsnd");
            return -1;
        }
        printf("sending successful\n");
        if(strncasecmp(sndbuf.mtext,"quit",4) == 0)
        {
            flag = 1;
            break;
        }
    }
    pthread_join(tid,NULL);
    pthread_join(tid_quit,NULL);
    return 0;
}

结果

Last modification:2021 年 04 月 07 日 23 : 06 : 50