news 2026/2/19 0:07:27

DAY46 Thread Mailbox System (C Language + Multi-thread Communication)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
DAY46 Thread Mailbox System (C Language + Multi-thread Communication)

Thread Mailbox System (C Language + Multi-thread Communication)

1. Core Positioning and Advantages

1.1 Core Objective

Enable asynchronous message passing between threads, allowing threads to communicate indirectly via “mailboxes” instead of direct interaction. This reduces logical coupling between threads while ensuring thread safety and data integrity in communication.

1.2 Key Advantages

  • Low Coupling: Threads only need to send/receive messages via mailbox names without knowing other threads’ IDs or logic. Modifying a single thread does not affect the overall system.
  • Easy Scalability: Adding new threads only requires registration to the mailbox system without modifying existing thread code.
  • Thread Safety: Critical resources are protected by mutex locks (pthread_mutex_t) to avoid concurrent access conflicts.
  • Lightweight: Implemented using native C and kernel-linked lists with no third-party dependencies, ensuring minimal resource usage.
  • Flexible Adaptation: Supports one-to-one or one-to-many message passing between arbitrary threads, with customizable message formats.

2. Core Architecture and Data Structures

1. Overall Architecture Diagram (Based on PDF Analysis)

┌─────────────────────────────────────────────────────────┐ │ Thread Mailbox System (MBS) │ │ ┌─────────────┐ ┌───────────┐ ┌─────────────────┐ │ │ │ Link Head (link_head) │ Mutex Lock (mutex) │ Thread Node List (LIST_DATA) │ │ │ └─────────────┘ └───────────┘ └─────────────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌─────────────┐ ┌───────────┐ ┌─────────────────┐ │ │ │ Thread A (data) │ Thread B (show) │ Thread C (sock) │ │ │ │ - Name: data │ - Name: show │ - Name: sock │ │ │ │ - Thread ID: tid│ - Thread ID: tid│ - Thread ID: tid │ │ │ │ - Message Queue │ - Message Queue │ - Message Queue │ │ │ │ - Thread Function│ - Thread Function│ - Thread Function │ │ │ └─────────────┘ └───────────┘ └─────────────────┘ │ └─────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────┐ ┌───────────┐ ┌─────────────────┐ │ Send Message │ │ Receive Message │ │ Receive Message │ │ Send_msg("show", data) │ Recv_msg() │ Recv_msg() │ │ Send_msg("sock", data) │ Print Message │ Print Message │ └─────────────┘ └───────────┘ └─────────────────┘

2. Core Data Structure Analysis

(1) Mailbox System Core Structure (MBS)
typedefstructmail_box_system{pthread_mutex_tmutex;// Protects critical resources (message queues, thread lists)structlist_headhead;// Thread node list head (reuses Linux kernel doubly linked list)}MBS;
  • mutex: Mutex lock ensuring thread safety during concurrent access.
  • head: Doubly linked list head managing all thread nodes registered in the mailbox system.
(2) Thread Node Structure (LIST_DATA)

Each thread registered in the mailbox system corresponds to a node storing core thread information:

typedefstructthread_node{pthread_ttid;// Thread IDcharname[256];// Unique thread name (for message addressing)LinkQue*lq;// Thread-specific message queue (stores received messages)th_fun th;// Thread function pointerstructlist_headnode;// Linked list node (connects to MBS's head list)}LIST_DATA;
(3) Message Structure (MAIL_DATA)

Message format for inter-thread communication, extendable as needed:

typedefstructmail_data{pthread_tid_of_sender;// Sender thread IDcharname_of_sender[256];// Sender thread namepthread_tid_of_recver;// Receiver thread IDcharname_of_recver[256];// Receiver thread namechardata[256];// Message content (extendable to any data type)}MAIL_DATA;
(4) Linked Queue Structure (LinkQue)

Used to store thread messages, implementing FIFO (First-In-First-Out) message delivery:

typedefstructquenode{DATATYPE data;// Message data (DATATYPE = MAIL_DATA)structquenode*next;// Next message node}LinkQueNode;typedefstruct_linkque{LinkQueNode*head;// Queue headLinkQueNode*tail;// Queue tailintclen;// Number of messages in the queue}LinkQue;

3. Core Function Implementation (Based on Code Breakdown)

The core workflow of the system is: “Create Mailbox System → Thread Registration → Message Sending/Receiving → System Destruction.” Below is a detailed breakdown of the key functional implementations.

1. Initialize Mailbox System (create_mail_box_system)

MBS*create_mail_box_system(){MBS*m_mbs=malloc(sizeof(MBS));if(NULL==m_mbs){perror("malloc failed");returnNULL;}INIT_LIST_HEAD(&m_mbs->head);// Initialize doubly linked list headpthread_mutex_init(&m_mbs->mutex,NULL);// Initialize mutex lockreturnm_mbs;}
  • Core Purpose: Allocates memory for the mailbox system, initializes the thread linked list and mutex lock, preparing for subsequent thread registration and message passing.
  • Key Technique:INIT_LIST_HEADis a Linux kernel macro for initializing linked lists, setting thenextandprevpointers of the list head to point to itself, forming an empty list.

2. Thread Registration (register_to_mail_system)

Threads must register with the mailbox system before sending/receiving messages:

intregister_to_mail_system(MBS*mbs,charname[],th_fun th){// 1. Allocate memory for thread nodeLIST_DATA*list_node=malloc(sizeof(LIST_DATA));if(NULL==list_node){perror("malloc failed");return1;}// 2. Initialize node info (name, message queue)strcpy(list_node->name,name);list_node->lq=CreateLinkQue();// Create dedicated message queue// 3. Add node to the thread linked list of the mailbox systemlist_add(&list_node->node,&mbs->head);// 4. Create thread (execute the passed thread function th)pthread_create(&list_node->tid,NULL,th,NULL);return0;}
  • Core Purpose: Creates a dedicated message queue for the thread, connects the thread node to the system linked list, and starts the thread.
  • Key Technique: Thelist_addmacro inserts the thread node after the list head, enabling efficient node addition.

3. Message Sending (send_msg)

Threads send messages via the recipient’s name without needing to know the recipient’s thread ID:

intsend_msg(MBS*mbs,char*recvname,MAIL_DATA*data){// 1. Locate sender's own node (via current thread ID)LIST_DATA*myself=find_node_byid(mbs,pthread_self());if(NULL==myself){fprintf(stderr,"find sender failed");return1;}// 2. Fill sender info in the messagedata->id_of_sender=pthread_self();strcpy(data->name_of_sender,myself->name);// 3. Locate recipient node (via recipient name)LIST_DATA*recver=find_node_byname(mbs,recvname);if(NULL==recver){fprintf(stderr,"find recver failed");return1;}// 4. Fill recipient info in the messagedata->id_of_recver=recver->tid;strcpy(data->name_of_recver,recver->name);// 5. Lock and enqueue the message (thread-safe)pthread_mutex_lock(&mbs->mutex);EnterLinkQue(recver->lq,data);// Enqueue message to recipient's queuepthread_mutex_unlock(&mbs->mutex);return0;}
  • Core Purpose: Encapsulates sender and recipient info, safely adding the message to the recipient’s message queue.
  • Thread Safety: Usespthread_mutex_lock/unlockto protect the enqueue operation, preventing concurrent write conflicts.

4. Message Receiving (recv_msg)

Threads read messages from their own message queues for asynchronous reception:

intrecv_msg(MBS*mbs,MAIL_DATA*data){// 1. Locate current thread's nodeLIST_DATA*myself=find_node_byid(mbs,pthread_self());if(NULL==myself){fprintf(stderr,"find self failed");return1;}// 2. Lock and read the message at the head of the queuepthread_mutex_lock(&mbs->mutex);MAIL_DATA*tmp=GetHeadLinkQue(myself->lq);if(NULL==tmp){// Queue empty, unlock and returnpthread_mutex_unlock(&mbs->mutex);return1;}// 3. Copy message to receive buffer, remove it from the queuememcpy(data,tmp,sizeof(MAIL_DATA));QuitLinkQue(myself->lq);// Dequeue messagepthread_mutex_unlock(&mbs->mutex);return0;}
  • Core Purpose: Reads messages from the thread’s dedicated queue in FIFO order.
  • No-Message Handling: Returns 1 if the queue is empty; threads can retry with a loop + sleep to avoid busy waiting.

5. System Destruction and Resource Release (destroy_mail_box_system)

voiddestroy_mail_box_system(MBS*mbs){LIST_DATA*pos,*q;// Traverse all thread nodes, delete and release resourceslist_for_each_entry_safe(pos,q,&mbs->head,node){list_del(&pos->node);// Remove node from the listfree(pos);// Free node memory}return;}
  • Key Technique:list_for_each_entry_safeis a kernel macro for safe traversal, using temporary variableqto store the next node, preventing list breakage after deleting the current node.

IV. Practical Usage Example (Based on main.c)

Below is a complete example demonstrating the workflow of the thread mailbox system: system creation → thread registration → message sending/receiving.

1. Thread Function Implementation

(1) Data Generation Thread (data_th)

Periodically generates simulated sensor data and sends it toshowandsockthreads:

void*data_th(void*arg){srand(time(NULL));MAIL_DATA data;while(1){// Generate simulated data between 30.00~39.99intnum=rand()%1000+3000;floattmp=num/100.0;bzero(&data,sizeof(data));sprintf(data.data,"temp:%.2f°C",tmp);// Message content// Send message to "show" threadsend_msg(g_mbs,"show",&data);sleep(rand()%3);// Random sleep 0~2 seconds// Send message to "sock" threadsend_msg(g_mbs,"sock",&data);sleep(rand()%2);// Random sleep 0~1 second}returnNULL;}
(2) Message Display Thread (show_th)

Continuously receives and prints messages:

void*show_th(void*arg){MAIL_DATA data;while(1){bzero(&data,sizeof(data));intret=recv_msg(g_mbs,&data);if(1==ret){sleep(1);continue;}// Sleep if no message// Print received messageprintf("[show thread] Received message from %s: %s\n",data.name_of_sender,data.data);}returnNULL;}
(3) Network Sending Thread (sock_th)

Simulates sending messages over the network (simplified as printing here):

void*sock_th(void*arg){MAIL_DATA data;while(1){bzero(&data,sizeof(data));intret=recv_msg(g_mbs,&data);if(1==ret){sleep(1);continue;}// Sleep if no message// Simulate network sendingprintf("[sock thread] Received message from %s (to be sent over network): %s\n",data.name_of_sender,data.data);}returnNULL;}

2. Main Function (Program Entry)

MBS*g_mbs;// Global mailbox system pointer (for easy access by thread functions)intmain(intargc,char**argv){// 1. Create mailbox systemg_mbs=create_mail_box_system();// 2. Register 3 threads: show, sock, dataregister_to_mail_system(g_mbs,"show",show_th);register_to_mail_system(g_mbs,"sock",sock_th);register_to_mail_system(g_mbs,"data",data_th);// 3. Wait for all threads to finish (blocking main thread)wait_all_end(g_mbs);// 4. Destroy mailbox system and release resourcesdestroy_mail_box_system(g_mbs);return0;}

3. Compilation and Execution

(1) Compilation Command (Requires linking pthread library)
gcc main.c mailbox.c linkque.c-othread_mailbox-lpthread
(2) Sample Execution Output
[show thread] Received message from data: temp:32.56°C [sock thread] Received message from data (to be sent over network): temp:32.56°C [show thread] Received message from data: temp:37.12°C [sock thread] Received message from data (to be sent over network): temp:35.89°C ...

V. Design Highlights and Technical Details

1. Reusing Linux Kernel Linked List (list.h)

  • Advantage: The kernel linked list is a proven efficient data structure that supports fast insertion, deletion, and traversal without manual implementation;
  • Key Macros:list_add(add node),list_del(delete node),list_for_each_entry_safe(safe traversal), simplifying thread node management.

2. Thread-Safe Design

  • Mutex (pthread_mutex_t): Protects concurrent access to the thread list and message queue, preventing data corruption from simultaneous multi-thread modifications;
  • Message Queue Isolation: Each thread has its own message queue, avoiding message confusion and reducing lock contention.

3. Low-Coupling Design

  • Thread Addressing: Uses thread names instead of IDs to find recipients, with thread IDs assigned by the system, making names easier to maintain;
  • Message Encapsulation: TheMAIL_DATAstructure standardizes message format, allowing senders and receivers to ignore each other’s implementation details;
  • Flexible Extension: New threads only need to callregister_to_mail_systemwithout modifying existing thread code.

VI. Extension Directions and Applicable Scenarios

1. Functional Extensions

  • Message Priority: Add apriorityfield toMAIL_DATAto sort message queues by priority, supporting urgent message processing;
  • Timeout Reception: Extendrecv_msgto support timeout settings, preventing infinite thread blocking;
  • Dynamic Deregistration: Addunregister_from_mail_systemto allow threads to exit the mailbox system during runtime;
  • Message Receipt: Add a message delivery confirmation mechanism to ensure messages are received.

2. Applicable Scenarios

  • Embedded Systems: Message passing from sensor data collection threads → data processing threads → network sending threads;
  • Multi-Module Collaboration: For example, in a web server, request receiving threads → business processing threads → response sending threads;
  • Logging Systems: Multiple business threads send log messages to a logging thread for unified printing or file writing.
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/6 18:22:41

零基础学会VM16许可证申请与使用

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个交互式VM16许可证使用教程应用,包含:1. 分步图文指南 2. 常见问题解答 3. 模拟激活流程 4. 错误代码查询 5. 测试用演示密钥生成。使用HTMLJavaScr…

作者头像 李华
网站建设 2026/2/19 4:26:45

【Linux】各种代码开发工具

一、各工具详细介绍 1. gvm(Go Version Manager) 核心定位 gvm 是一款专门用于管理 Go 语言(Golang)多版本环境的轻量级命令行工具,核心目标是解决 Go 语言不同版本之间的快速切换、安装、卸载及环境隔离问题&#xff…

作者头像 李华
网站建设 2026/2/19 5:08:42

IDEA 2025.3 vs 传统IDE:开发效率对比实验

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容: 创建一个包含多个编程任务的基准测试项目,比较IDEA 2025.3和传统IDE(如Eclipse)完成相同任务所需的时间。任务应包括类创建、方法重构、调试会话…

作者头像 李华
网站建设 2026/2/17 1:46:04

如何在JupyterLab中启动VibeVoice-WEB-UI?1键脚本快速入门

如何在JupyterLab中启动VibeVoice-WEB-UI?1键脚本快速入门 你有没有遇到过这样的场景:手头有一段多人对话文本,想快速生成一段自然流畅的语音音频,用于播客、教学或原型演示,但市面上的TTS工具要么机械感太强&#xff…

作者头像 李华
网站建设 2026/2/7 6:27:11

工业现场抗干扰设计中三极管稳定工作的关键因素

工业现场为何三极管总“抽风”?5大设计陷阱与实战避坑指南在工业自动化系统中,一个看似简单的NPN三极管,常常承担着驱动继电器、控制电磁阀或点亮报警灯的关键任务。它结构简单、成本低廉,但偏偏就是这个“最基础”的器件&#xf…

作者头像 李华
网站建设 2026/2/17 12:27:58

高亮度LED恒流驱动电路深度剖析

高亮度LED恒流驱动:从原理到实战的系统性拆解你有没有遇到过这样的情况?明明选了高品质的LED灯珠,电路也照着典型应用图连好了,结果点亮后光输出忽明忽暗,甚至用不了几天就烧了MOS管。问题出在哪?十有八九&…

作者头像 李华