1.线程邮箱系统框图

2.主要函数步骤
创建MBS---->注册线程---->等待mbs结束---->销毁邮箱系统
1.g_mbs = create_mail_box_system();
2.register_to_mail_system(g_mbs, "show", show_th);
3.wait_all_end(g_mbs);
4.destroy_mail_box_system(g_mbs);
MBS的创建并初始化
cpp
MBS*create_mail_box_system()
{
MBS*m_mbs = malloc(sizeof(MBS));
if(NULL == m_mbs)
{
perror("create error");
return NULL;
}
INIT_LIST_HEAD(&m_mbs->head);
pthread_mutex_init(&m_mbs->mutex,NULL);
return m_mbs;
}
创建节点并注册
cpp
int register_to_mail_system(MBS*mbs,char name[],th_fun th)
{
LIST_DATA*list_node=malloc(sizeof(LIST_DATA)); // 分配用户节点内存
if(NULL == list_node)
{
perror("register malloc");
return 1;
}
strcpy(list_node->name,name); // 复制用户名
list_node->lq=CreateLinkQue(); // 为该用户创建专属消息队列
list_add(&list_node->node,&mbs->head); // 将节点添加到MBS的链表中
pthread_create(&list_node->tid,NULL,th,NULL); // 创建用户对应的线程
return 0;
}
等待结束
cpp
int wait_all_end(MBS*mbs)
{
LIST_DATA *pos, *q;
// 安全遍历链表(遍历时可能删除节点,q用于保存下一个节点)
list_for_each_entry_safe(pos, q, &mbs->head, node)
{
pthread_join(pos->tid, NULL); // 等待该用户线程结束
}
return 0;
}
按名称/线程id查找用户节点
cpp
LIST_DATA* find_node_byname(MBS* mbs, char* name)
{
LIST_DATA *pos, *q;
list_for_each_entry_safe(pos, q, &mbs->head, node)
{
if (0 == strcmp(pos->name, name)) // 字符串匹配
{
return pos; // 找到则返回节点
}
}
return NULL; // 未找到返回NULL
}
cpp
LIST_DATA* find_node_byid(MBS* mbs, pthread_t id)
{
LIST_DATA *pos, *q;
list_for_each_entry_safe(pos, q, &mbs->head, node)
{
if (pos->tid == id) // 线程ID匹配
{
return pos;
}
}
return NULL;
}
发送消息
cpp
int send_msg(MBS* mbs, char* recvname, MAIL_DATA* data)
{
// 1. 找到发送者自身节点(通过当前线程ID)
LIST_DATA* myself = find_node_byid(mbs, pthread_self());
if (NULL == myself)
{
fprintf(stderr, "sendmsg error ,find myself id\n");
return 1;
}
// 2. 填充发送者信息到邮件
data->id_of_sender = pthread_self();
strcpy(data->name_of_sender, myself->name);
// 3. 找到接收者节点(通过接收者名称)
LIST_DATA* recver = find_node_byname(mbs, recvname);
if (NULL == recver)
{
fprintf(stderr, "sendmsg error ,find recver name\n");
return 1;
}
// 4. 填充接收者信息到邮件
data->id_of_recver = recver->tid;
strcpy(data->name_of_recver, recver->name);
// 5. 加锁后将邮件放入接收者的消息队列
pthread_mutex_lock(&mbs->mutex);
EnterLinkQue(recver->lq, data);
pthread_mutex_unlock(&mbs->mutex);
return 0;
}
接收消息
cpp
int recv_msg(MBS* mbs, MAIL_DATA* data)
{
// 1. 找到接收者自身节点
LIST_DATA* myself = find_node_byid(mbs, pthread_self());
if (NULL == myself)
{
fprintf(stderr, "recv_msg find_node_byid myself\n");
return 0;
}
pthread_mutex_lock(&mbs->mutex);
// 2. 获取消息队列队头(不删除)
MAIL_DATA* tmp = GetHeadLinkQue(myself->lq);
if (NULL == tmp) // 队列为空,无消息
{
pthread_mutex_unlock(&mbs->mutex);
return 1;
}
// 3. 复制消息到输出参数data
memcpy(data, tmp, sizeof(MAIL_DATA));
// 4. 出队(删除队头)
QuitLinkQue(myself->lq);
pthread_mutex_unlock(&mbs->mutex);
return 0;
}
销毁邮箱系统
cpp
void destroy_mail_box_system(MBS* mbs)
{
LIST_DATA *pos, *q;
list_for_each_entry_safe(pos, q, &mbs->head, node)
{
list_del(&pos->node);
free(pos);
}
return;
}
总结:
核心逻辑:基于 Linux 内核链表管理用户节点,每个用户绑定线程和独立消息队列,通过互斥锁保证多线程消息收发的安全性;
核心函数:create_mail_box_system(创建)→register_to_mail_system(注册)→send_msg/recv_msg(收发消息)→wait_all_end(等待线程)→destroy_mail_box_system(销毁);
关键优化点:补充内存释放、加锁遍历链表、替换不安全字符串操作、完善错误检查。