版本更换通知:从第七章开始,我把分析的源码版本升到了1.7.5-beta。在已经分析过的代码中存在了一些变动,但没有到会影响理解的地步,所以再次不再更新前面的章节。如果确认前面的章节有重大变更需要重新分析的,我会给出声明。
Swoole内部封装了Linux提供的msg queue用于提供消息队列的操作。消息队列的声明在swoole.h文件的360 – 378 行。声明如下:
typedef struct _swQueue_Data
{
long mtype; /* type of received/sent message*/
char mdata[sizeof(swEventData)]; /* text ofthe message */
} swQueue_data;
typedef struct _swQueue
{
void *object;
int blocking;
int (*in)(struct _swQueue *, swQueue_data *in, int data_length);
int (*out)(struct _swQueue *, swQueue_data *out, int buffer_length);
void (*free)(struct _swQueue *);
int (*notify)(struct _swQueue *);
int (*wait)(struct _swQueue *);
} swQueue;
int swQueueMsg_create(swQueue *p, int wait,int msg_key, long type);
第一个结构体swQueue_Data封装了消息队列中的消息,其中mtype 用于标记该消息是需要发送的消息还是从队列中读出的消息,mdata用于存放消息内容(swEventData结构体将在下一章解析)。
最后一行的函数用于创建一个消息队列,第二个参数wait指定阻塞类型,msg_key指定创建的消息队列的键值,type标记消息队列读数据的类型
type=0,接受该队列的第一个消息,并将它返回给调用者
type>0,接受类型type的第一个消息
type<0,接受小于等于type绝对值的最低类型的第一个消息
swQueueMsg_create函数的具体声明在Msg.c文件中,其核心代码如下:
swQueueMsg*object = sw_malloc(sizeof(swQueueMsg));
if(object == NULL)
{
return-1;
}
if(blocking == 0)
{
object->ipc_wait= IPC_NOWAIT;
}
else
{
object->ipc_wait= 0;
}
p->blocking= blocking;
msg_id= msgget(msg_key, IPC_CREAT | O_EXCL | 0666);
源码解释:申请内存,分配消息队列的结构体内存,并判定消息队列的阻塞类型。接着调用msgget函数创建消息队列。
这里说明msgget第三个参数中的几个值的意义。IPC_CREAT表明,若不存在以key为索引的消息队列,则创建新的队列;否则,返回已创建的消息队列的id。O_EXCL表示若打开一个已存在的消息队列,则返回-1。0666为该消息队列的读写权限。
swQueueMsg有对应的三个操作函数,分别是:
int swQueueMsg_in(swQueue *p, swQueue_data*in, int data_length);
int swQueueMsg_out(swQueue *p, swQueue_data*out, int buffer_length);
void swQueueMsg_free(swQueue *p);
这三个函数用于向队列中写入消息、从队列中读出消息、释放队列。
1. swQueueMsg_in函数循环调用msgsnd直到消息发送成功或无法再次发送。
2. swQueueMsg_out函数调用msgrcv函数接收指定类型的消息
3. swQueueMsg_free函数调用msgctl释放一个消息队列,IPC_RMID参数代表立即释放全部资源。
PS:最近一直在忙面试和公司的事情,所以停更了很久。这次只更一个小章,下一个大章已经在写了,顺利的话会在明天放出。如果觉得我写的blog对你有所帮助,或者对我的分析有一些见解,欢迎在下方评论或发邮件给我。
我的邮箱地址:[email protected]