在做linux多任务编程的时候,难免会碰到要使用IPC技术了,但是很多人都对这些技术只知其名,不知道如何使用。为了大家都能很好的学习Linux,本人不才,贴出了自己写的 消息队列 编程,用的是多线程,不是多进程,原理一样。以后有时间会后续把其他几个技术一一详解,并贴上代码。好了,废话不多说,进入下面的实例讲解。
/*****************************************************
**头文件包含
****************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h> //ftok, msgget, msgrcv, msgsnd
#include <sys/ipc.h> //ftok, msgget, msgrcv, msgsnd
#include <sys/msg.h> //ftok, msgget, msgrcv, msgsnd
#include <pthread.h> //多线程
#include <string.h> //memcpy
#include <unistd.h>
#define KEYFILE "/root/work/msgqueue" //产生系统唯一的键值所用,这个目录或文件一定要存在
#define PROJID 10 //产生系统唯一的键值项目号。
struct msg{
long type; //消息类型
char buf[512]; //消息内容
};
/*******************************************************
**创建系统唯一的键值,为msgget所用,也可以不
**用调用此函数,用一个常数代替key,但是为避免
**创建的消息队列失败,建议用此方法。
*******************************************************/
key_t CreateMsgKey()
{
return ftok(KEYFILE,PROJID);//系统调用,返回一个系统唯一的键值。
}
/********************************************************
**下面是创建一个线程,并设置为分离态,这个应该
**就不需要多说了吧。
*********************************************************/
pthread_t createthread(void* (*fun)(void *),void *arg)
{
pthread_t threadId;
pthread_attr_t attr;
memset(&attr,0,sizeof(attr));
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
return pthread_create(&threadId,&attr,fun,arg);
}
/*******************************************
**待会要创建的线程工作函数,此线程
**每隔2秒向消息队列里发一条消息。
********************************************/
void *DoSndMsg(void *arg)
{
struct msg SndMsg;
long iCount=1;
SndMsg.type=100;//消息类型为100
int msgid=0;
msgid=msgget(*(key_t *)arg,IPC_CREAT);//获取消息队列的ID,arg是由进程传进来的key,IPC_CREAT表示创建一个新的
//消息队列,如果,如果key已经创建了消息队列,则返回已经创建的消息队列ID。
//如果IPC_EXCL | IPC_CREAT一起用,如果key已经创建了消息队列,则返回错误。
printf("msgid is:%d\n",msgid); //打印下msgid
while(iCount>0)
{
iCount+=1;;
memcpy(SndMsg.buf,&iCount,sizeof(iCount));
msgsnd(msgid,&SndMsg,sizeof(SndMsg),IPC_NOWAIT);//把sndmsg里的消息发送到msgid的消息队列里,IPC_NOWAIT表示
//不阻 塞。
printf("iCount is:%ld\n",iCount);
sleep(2);
}
return NULL;
}
int main()
{
pthread_t sndThread;
struct msg rcvMsg;
int msgid;
long rcvCount=0;
key_t msgkey;
msgkey=CreateMsgKey(); //创建key
sndThread=createthread(DoSndMsg,&msgkey);//创建线程。
msgid=msgget(msgkey,IPC_CREAT);//获取消息队列ID
printf("msgid is:%d\n",msgid);
while(rcvCount==0)
{
msgrcv(msgid,&rcvMsg,sizeof(rcvMsg),0,IPC_NOWAIT);//接收msgid里第一条消息,0的位置是消息类型,0,表示消息队列
//第一条消息,大于零的值则表示收取相应消息类型的消息。
memcpy(&rcvCount,rcvMsg.buf,sizeof(rcvCount));
printf("msgtype:%ld\n",rcvMsg.type);
printf("rcvCount is:%ld\n",rcvCount);
sleep(2);
rcvCount=0;
}
return EXIT_SUCCESS;
}
系统调用msgrcv中的参数type非常的重要,这个形参决定读取消息队列中哪一条消息,unix环境高级编程里做了很好的总结,现在分享给大家。
type==0, 表示读取消息队列中的第一条消息(任何类型的消息都接收);
type>0, 表示读取消息队列中类型为type的第一条消息(如果有多条同类型消息,一次只读最前面的一条消息);
type<0, 表示读取消息队列中类型为小于或者大于type绝对值的第一条消息。