线程消息队列c语言,基于C语言的线程通信消息队列实现

#include #include "msg_process.h"

#define LOG_ERR(fmt, ...) do{\

printf("[ERROR] "fmt" [line:%d] [%s]\n", ##__VA_ARGS__, __LINE__, __FUNCTION__);\

}while(0);

static unsigned long timeout_ns = 0;

/**

* 消息处理模块内部接口

*/

static void put_msg_to_buffer(tmsg_buffer* buf, tmsg_element* elm){

if (NULL == buf || NULL == elm) {

return;

}

if (NULL != elm->next) {

elm->next = NULL;

}

pthread_mutex_lock(&buf->mutex);

//缓冲区中无消息节点

if (0 == buf->num) {

gettimeofday(&timenow,NULL);

timeout.tv_sec = timenow.tv_sec + block/1000; //加上秒数

block %= 1000;//得到毫秒数

timeout_ns = timenow.tv_usec*1000 + block*1000*1000;

if( timeout_ns >= 1000*1000*1000 ) //若超过1s

{

timeout.tv_sec ++;

timeout.tv_nsec = timeout_ns - 1000*1000*1000;

}

else

timeout.tv_nsec = timeout_ns;

//带超时时间阻塞线程等待消息节点

pthread_cond_timedwait(&buf->not_empty, &buf->mutex, &timeout);

}

pthread_mutex_unlock(&buf->mutex);

}

static tmsg_element* get_msg_from_buffer(tmsg_buffer* buf, int block){

tmsg_element *elm = NULL;

if (NULL == buf) {

return NULL;

}

pthread_mutex_lock(&buf->mutex);

//缓冲区中无消息节点

while (0 == buf->num) {

//阻塞线程等待消息节点

pthread_cond_wait(&buf->not_empty, &buf->mutex);

}

//从缓冲区首部取出消息节点

elm = buf->first;

if (1 == buf->num) {

buf->first = buf->last = NULL;

buf->num = 0;

} else {

buf->first = buf->first->next;

buf->num --;

}

pthread_mutex_unlock(&buf->mutex);

return elm;

}

static tmsg_element* get_msg_from_buffer_timeout(tmsg_buffer* buf, int block/*ms*/){

tmsg_element *elm = NULL;

struct timeval timenow;

struct timespec timeout;

if (NULL == buf) {

return NULL;

}

pthread_mutex_lock(&buf->mutex);

//缓冲区中无消息节点

if (0 == buf->num) {

gettimeofday(&timenow);

timeout.tv_sec = timenow.tv_sec;

timeout.tv_nsec = (timenow.tv_usec + block * 1000) * 1000;

//带超时时间阻塞线程等待消息节点

pthread_cond_timedwait(&buf->not_empty, &buf->mutex, &timeout);

}

if (buf->num > 0) {

//从缓冲区首部取出消息节点

elm = buf->first;

if (1 == buf->num) {

buf->first = buf->last = NULL;

buf->num = 0;

} else {

buf->first = buf->first->next;

buf->num --;

}

}

pthread_mutex_unlock(&buf->mutex);

return elm;

}

static tmsg_element* clear_msg_buffer(tmsg_buffer* buf){

tmsg_element* elm = NULL;

tmsg_element* elm_tmp = NULL;

if (NULL == buf){

return NULL;

}

//清空buffer中当前消息节点之前的所有消息节点

pthread_mutex_lock(&buf->mutex);

if (buf->num > 0) {

elm = buf->first;

while(elm != NULL) {

//首尾指针指向同一消息节点

if (elm == buf->last) {

buf->first = buf->last;

if (buf->num != 1) {

buf->num = 1;

}

break;

}

elm_tmp = elm->next;

free_tmsg_element(elm);

buf->num --;

elm = elm_tmp;

buf->first = elm;

}

}

pthread_mutex_unlock(&buf->mutex);

return elm;

}

static void send_msg_to_buffer(tmsg_buffer* buf, int msg, int ext, char* str, int len)

{

tmsg_element *elm = NULL;

elm = (tmsg_element *)malloc(sizeof(tmsg_element));

if (NULL == elm) {

LOG_ERR("new msg element failed!!");

return;

}

//填充消息节点数据

memset(elm, 0, sizeof(tmsg_element));

elm->msg = msg;

elm->ext = ext;

elm->dt = NULL;

elm->dt_len = len;

if (str)

{

elm->dt = (char *)malloc(len); //根据发送的大小申请内存

memmove(elm->dt, str, len);

}

elm->next = NULL;

//将消息节点添加到缓冲区中

put_msg_to_buffer(buf, elm);

}

static void send_msg_to_buffer_ex(tmsg_buffer* buf, int msg, int ext, int sub0, int sub1, char* str, int len){

tmsg_element *elm = NULL;

elm = (tmsg_element *)malloc(sizeof(tmsg_element));

if (NULL == elm) {

LOG_ERR("new msg element failed!!");

return;

}

//填充消息节点数据

memset(elm, 0, sizeof(tmsg_element));

elm->msg = msg;

elm->ext = ext;

elm->sub0 = sub0;

elm->sub1 = sub1;

elm->dt = NULL;

elm->dt_len = len;

if (str)

{

elm->dt = (char *)malloc(len); //根据发送的大小申请内存

memmove(elm->dt, str, len);

}

elm->next = NULL;

//将消息节点添加到缓冲区中

put_msg_to_buffer(buf, elm);

}

static void dispose_msg_buffer(tmsg_buffer* buf){

tmsg_element* elm = NULL;

if (NULL == buf) {

return;

}

if (buf->first != buf->last

&& buf->num > 0) {

elm = clear_msg_buffer(buf);

} else {

elm = buf->last;

}

if (NULL != elm) {

free_tmsg_element(elm);

buf->first = buf->last = NULL;

buf->num = 0;

}

pthread_mutex_destroy(&buf->mutex);

pthread_cond_destroy(&buf->not_empty);

free(buf);

buf = NULL;

}

static int get_msg_num(tmsg_buffer* buf){

if (NULL == buf) {

return 0;

}

return buf->num;

}

/**

* 以下为消息处理模块对外接口

*/

/*消息缓冲区初始化*/

tmsg_buffer* msg_buffer_init(void){

tmsg_buffer* msg_buffer = NULL;

msg_buffer = (tmsg_buffer *)malloc(sizeof(tmsg_buffer));

if (NULL == msg_buffer){

LOG_ERR("init msg buffer failed!!");

return NULL;

}

//初始化成员变量和函数

memset(msg_buffer, 0, sizeof(tmsg_buffer));

msg_buffer->first = NULL;

msg_buffer->last = NULL;

msg_buffer->num = 0;

pthread_mutex_init(&(msg_buffer->mutex), NULL);

pthread_cond_init(&(msg_buffer->not_empty), NULL);

//继续绑定接口

msg_buffer->put = put_msg_to_buffer;

msg_buffer->get = get_msg_from_buffer;

msg_buffer->get_timeout = get_msg_from_buffer_timeout;

msg_buffer->clear = clear_msg_buffer;

msg_buffer->sendmsg = send_msg_to_buffer;

msg_buffer->sendmsgex = send_msg_to_buffer_ex;

msg_buffer->dispose = dispose_msg_buffer;

msg_buffer->getnum = get_msg_num;

return msg_buffer;

}

/*复制消息节点*/

tmsg_element* dup_msg_element(tmsg_element* elm){

tmsg_element* msg_element = NULL;

if (NULL == elm) {

LOG_ERR("msg element is NULL!!");

return NULL;

}

msg_element = (tmsg_element *)malloc(sizeof(tmsg_element));

if (NULL == msg_element) {

LOG_ERR("create msg element is failed!!");

return NULL;

}

memcpy(msg_element, elm, sizeof(tmsg_element));

return msg_element;

}

void free_tmsg_element(tmsg_element *msg_element)

{

if(msg_element != NULL)

{

if(msg_element->dt != NULL)

{

free(msg_element->dt);

msg_element->dt = NULL;

}

free(msg_element);

msg_element = NULL;

}

}

好的,以下是一个用消息队列C语言实现线程通信的简单例子。 假设有两个线程,一个是生产者线程,一个是消费者线程,需要通过消息队列实现通信。其中,生产者线程需要将数据写入消息队列,消费者线程则从消息队列中读取数据进行处理。 首先,需要定义一个消息结构体,例如: ```c struct message { long mtype; // 消息类型 char mtext[1024]; // 消息内容 }; ``` 然后,在生产者线程中,可以使用以下代码将数据写入消息队列: ```c #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> key_t key = ftok("path/to/file", 'a'); // 获取消息队列的键值 int msgid = msgget(key, 0666 | IPC_CREAT); // 创建消息队列 struct message msg; msg.mtype = 1; // 假设消息类型为1 strcpy(msg.mtext, "Hello, world!"); // 假设要发送的消息内容为 "Hello, world!" msgsnd(msgid, &msg, sizeof(msg), 0); // 将消息发送到消息队列中 ``` 在消费者线程中,可以使用以下代码从消息队列中读取数据: ```c #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> key_t key = ftok("path/to/file", 'a'); // 获取消息队列的键值 int msgid = msgget(key, 0666 | IPC_CREAT); // 获取消息队列的ID struct message msg; msgrcv(msgid, &msg, sizeof(msg), 1, 0); // 从消息队列中接收消息类型为1的消息 printf("Received message: %s\n", msg.mtext); // 处理接收到的消息 ``` 需要注意的是,消息队列中的消息类型必须是正整数,可以自定义。在发送消息时,需要指定消息类型;在接收消息时,需要指定要接收的消息类型。另外,需要在程序结束时删除消息队列,以释放资源: ```c msgctl(msgid, IPC_RMID, NULL); // 删除消息队列 ``` 以上就是一个简单的用消息队列C语言实现线程通信的例子。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值