diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day2/day2.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day2/day2.c" new file mode 100644 index 0000000000000000000000000000000000000000..5ace8a43e97e5c4808deabe6ec99808fc7221328 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day2/day2.c" @@ -0,0 +1,67 @@ +#include +#include +#include + +#define thread_stack_size 512 +#define thread_tick 5 + +#define THREAD1_PRIORITY 10 // 高优先级 +#define THREAD2_PRIORITY 12 // 中优先级 +#define MAIN_THREAD_PRIORITY 15 // 低优先级(main 线程) + +void thread1_entry(void *param) +{ + while (1) + { + rt_kprintf(">>> this is HIGH priority thread1\n"); + rt_thread_mdelay(500); + } +} + +void thread2_entry(void *param) +{ + while (1) + { + rt_kprintf(" >>> this is MEDIUM priority thread2\n"); + rt_thread_mdelay(500); + } +} + +int main(void) +{ + rt_thread_t thread1 = RT_NULL; + rt_thread_t thread2 = RT_NULL; + + // 创建高优先级线程 thread1 + thread1 = rt_thread_create("th1", + thread1_entry, + RT_NULL, + thread_stack_size, + THREAD1_PRIORITY, // 优先级 10 + thread_tick); + // 创建中优先级线程 thread2 + thread2 = rt_thread_create("th2", + thread2_entry, + RT_NULL, + thread_stack_size, + THREAD2_PRIORITY, // 优先级 12 + thread_tick); + + if (thread1 != RT_NULL) + rt_thread_startup(thread1); + + if (thread2 != RT_NULL) + rt_thread_startup(thread2); + + // 主线程降低优先级以体现对比 + rt_thread_t main_thread = rt_thread_self(); + rt_thread_set_priority(main_thread, MAIN_THREAD_PRIORITY); // 设为低优先级 + + while (1) + { + rt_kprintf(" >>> this is LOW priority main thread\n"); + rt_thread_mdelay(500); + } + + return RT_EOK; +} \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/event.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/event.c" new file mode 100644 index 0000000000000000000000000000000000000000..2de6b190a238931d2f4bb4642bf6eb5d3b9b96bb --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/event.c" @@ -0,0 +1,65 @@ +// mailbox.c +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_event_t event = RT_NULL; +#define EVT_START 0x01 +#define EVT_DONE 0x02 + +// 任务线程(等待事件) +static void worker_entry(void *parameter) +{ + rt_uint32_t recved; + + while (1) + { + // 等待启动事件 + if (rt_event_recv(event, EVT_START, RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR, + RT_WAITING_FOREVER, &recved) == RT_EOK) + { + rt_kprintf("Worker: Task started...\n"); + rt_thread_mdelay(500); + rt_kprintf("Worker: Task done, sending EVT_DONE\n"); + rt_event_send(event, EVT_DONE); // 通知完成 + } + } +} + +// 控制线程(触发事件) +static void ctrl_entry(void *parameter) +{ + while (1) + { + rt_kprintf("Ctrl: Sending EVT_START\n"); + rt_event_send(event, EVT_START); + rt_thread_mdelay(2000); + } +} + +int event_demo(void) +{ + rt_thread_t tid1, tid2; + + event = rt_event_create("ev", RT_IPC_FLAG_FIFO); + if (event == RT_NULL) + { + rt_kprintf("Failed to create event!\n"); + return -1; + } + + tid1 = rt_thread_create("worker", worker_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + tid2 = rt_thread_create("ctrl", ctrl_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} +INIT_APP_EXPORT(event_demo); \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/mailbox.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/mailbox.c" new file mode 100644 index 0000000000000000000000000000000000000000..6bea08d7961c35b7e80d8a8df4606ed92eb4272b --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/mailbox.c" @@ -0,0 +1,62 @@ +// mailbox.c +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_mb_t mb = RT_NULL; + +// 发送线程 +static void sender_entry(void *parameter) +{ + rt_uint32_t data; + while (1) + { + data = rt_tick_get(); // 用 tick 作为数据 + rt_kprintf("Sender: Sending data %d\n", data); + if (rt_mb_send(mb, (rt_uint32_t)data) != RT_EOK) + { + rt_kprintf("Sender: Mailbox full!\n"); + } + rt_thread_mdelay(1000); + } +} + +// 接收线程 +static void receiver_entry(void *parameter) +{ + rt_uint32_t data; + while (1) + { + if (rt_mb_recv(mb, &data, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("Receiver: Received data %d\n", data); + } + } +} + +int mailbox_demo(void) +{ + rt_thread_t tid1, tid2; + + mb = rt_mb_create("mbx", 4, RT_IPC_FLAG_FIFO); // 邮箱容量 4 + if (mb == RT_NULL) + { + rt_kprintf("Failed to create mailbox!\n"); + return -1; + } + + tid1 = rt_thread_create("sender", sender_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + tid2 = rt_thread_create("receiver", receiver_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} +INIT_APP_EXPORT(mailbox_demo); \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/msgqueue.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/msgqueue.c" new file mode 100644 index 0000000000000000000000000000000000000000..24bb527075b81ffffc2d2bce79ac99a3ea614b89 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/msgqueue.c" @@ -0,0 +1,70 @@ +// msgqueue.c +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 1024 +#define THREAD_TIMESLICE 5 + +struct msg_data +{ + rt_uint32_t id; + char str[32]; +}; + +static rt_mq_t mq = RT_NULL; + +// 发送线程 +static void sender_entry(void *parameter) +{ + struct msg_data msg; + rt_uint32_t id = 0; + while (1) + { + msg.id = id++; + rt_sprintf(msg.str, "Hello-%d", msg.id); + rt_kprintf("Sender: Sending message ID=%d\n", msg.id); + if (rt_mq_send(mq, &msg, sizeof(struct msg_data)) != RT_EOK) + { + rt_kprintf("Sender: Message queue full!\n"); + } + rt_thread_mdelay(1000); + } +} + +// 接收线程 +static void receiver_entry(void *parameter) +{ + struct msg_data msg; + while (1) + { + if (rt_mq_recv(mq, &msg, sizeof(struct msg_data), RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("Receiver: Got ID=%d, str=%s\n", msg.id, msg.str); + } + } +} + +int msgqueue_demo(void) +{ + rt_thread_t tid1, tid2; + + mq = rt_mq_create("mq", sizeof(struct msg_data), 4, RT_IPC_FLAG_FIFO); + if (mq == RT_NULL) + { + rt_kprintf("Failed to create message queue!\n"); + return -1; + } + + tid1 = rt_thread_create("sender", sender_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + tid2 = rt_thread_create("receiver", receiver_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} +INIT_APP_EXPORT(msgqueue_demo); \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/mutex.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/mutex.c" new file mode 100644 index 0000000000000000000000000000000000000000..7d7aa7383b6f728380c9c3a2d06666bb4e819aa8 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/mutex.c" @@ -0,0 +1,53 @@ +// mutex.c +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_mutex_t mutex = RT_NULL; +static int shared_counter = 0; + +// 线程入口函数 +static void thread_entry(void *parameter) +{ + char *name = (char *)parameter; + while (1) + { + // 获取互斥量 + if (rt_mutex_take(mutex, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("%s: Counter = %d\n", name, shared_counter); + shared_counter++; + rt_thread_mdelay(100); // 模拟临界区操作 + rt_mutex_release(mutex); // 释放 + } + rt_thread_mdelay(50); // 非临界区 + } +} + +int mutex_demo(void) +{ + rt_thread_t tid1, tid2; + + // 创建互斥量 + mutex = rt_mutex_create("mtx", RT_IPC_FLAG_FIFO); + if (mutex == RT_NULL) + { + rt_kprintf("Failed to create mutex!\n"); + return -1; + } + + tid1 = rt_thread_create("thread1", thread_entry, "T1", + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + tid2 = rt_thread_create("thread2", thread_entry, "T2", + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} +INIT_APP_EXPORT(mutex_demo); \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/sem.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/sem.c" new file mode 100644 index 0000000000000000000000000000000000000000..b17257db50c0f41dacd431961cb507e762651b36 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/sem.c" @@ -0,0 +1,60 @@ +// sem.c +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 512 +#define THREAD_TIMESLICE 5 + +static rt_sem_t sem = RT_NULL; // 信号量 + +// 生产者线程 +static void producer_entry(void *parameter) +{ + while (1) + { + rt_thread_mdelay(1000); + rt_kprintf("Producer: Posting semaphore\n"); + rt_sem_release(sem); // 释放信号量 + } +} + +// 消费者线程 +static void consumer_entry(void *parameter) +{ + while (1) + { + // 等待信号量 + if (rt_sem_take(sem, RT_WAITING_FOREVER) == RT_EOK) + { + rt_kprintf("Consumer: Got semaphore, processing data...\n"); + } + } +} + +int sem_demo(void) +{ + rt_thread_t tid1, tid2; + + // 创建信号量 + sem = rt_sem_create("sem1", 0, RT_IPC_FLAG_FIFO); + if (sem == RT_NULL) + { + rt_kprintf("Failed to create semaphore!\n"); + return -1; + } + + // 创建生产者线程 + tid1 = rt_thread_create("producer", producer_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + // 创建消费者线程 + tid2 = rt_thread_create("consumer", consumer_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} +INIT_APP_EXPORT(sem_demo); \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/signal.c" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/signal.c" new file mode 100644 index 0000000000000000000000000000000000000000..f90a2783e7142b8f9506f872a3e16c80867aa495 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\344\275\234\344\270\232/day3/signal.c" @@ -0,0 +1,63 @@ +// signal.c +#include +#include + +#define THREAD_PRIORITY 20 +#define THREAD_STACK_SIZE 1024 +#define THREAD_TIMESLICE 5 + +static rt_thread_t sig_thread = RT_NULL; + +// 信号处理函数 +void signal_handler(int sig) +{ + rt_kprintf("Signal %d received in thread: %s\n", sig, rt_thread_self()->name); +} + +// 信号接收线程 +static void sig_entry(void *parameter) +{ + rt_kprintf("Signal thread started, PID: %d\n", getpid()); + + // 注册信号处理函数 + signal(SIGUSR1, signal_handler); + + // 无限等待信号(实际由系统调度) + while (1) + { + rt_thread_mdelay(1000); + } +} + +// 发送信号的线程 +static void sender_entry(void *parameter) +{ + while (1) + { + rt_thread_mdelay(3000); + rt_kprintf("Sender: Sending SIGUSR1 to thread %s\n", sig_thread->name); + pthread_kill(sig_thread->tid, SIGUSR1); + } +} + +int signal_demo(void) +{ + rt_thread_t tid1, tid2; + + // 创建信号接收线程 + sig_thread = rt_thread_create("sig_recv", sig_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY - 1, THREAD_TIMESLICE); + if (sig_thread != RT_NULL) + { + rt_thread_startup(sig_thread); + } + + // 创建发送线程 + tid2 = rt_thread_create("sig_send", sender_entry, RT_NULL, + THREAD_STACK_SIZE, THREAD_PRIORITY, THREAD_TIMESLICE); + if (tid2 != RT_NULL) + rt_thread_startup(tid2); + + return 0; +} +INIT_APP_EXPORT(signal_demo); \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day1.md" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day1.md" new file mode 100644 index 0000000000000000000000000000000000000000..ec4bab36bc052401631e946efa22788702884fc5 --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day1.md" @@ -0,0 +1,20 @@ +一:上午学了env环境配置 +env下载:https://download-redirect.rt-thread.org/download/env_release/env-windows-v2.0.0.7z + +RT-Thread源码下载:RT-Thread/rt-thread: RT-Thread is an open source IoT Real-Time Operating System (RTOS) +1.先下载好git和env,用git对RT-Thread源码进行拉取(在git中输入git clone “网址”)。 +2.对env配置 +scons -4j//对文件进行编译 pkgs --upgrade//升级软件包 menuconfig//打开图形化配置界面 +3.运行LVGL示例程序 +打开env命令行,运行menuconfig,然后选择Hardware Drivers Config -> Onboard Periperal Drivers,可以看到有Enable LVGL for LCD和Enable LVGL Demo,全部启用即可: +然后运行pkgs —update更新一下当前工程的包,运行scons -j4编译,编译完成后直接运行qemu即可启动示例demo +下午:git仓库 +git add 暂存 +git commit 提交 +git log 查看历史 +git checkout/git reset 回退 +git branch 创建分支 +git merge 合并分支 +git push/pull 推送/拉取 +git status 查看文件状态 + diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day2.md" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day2.md" new file mode 100644 index 0000000000000000000000000000000000000000..6bc902ca6467bc734cb02b009a3aecb45d771f6e --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day2.md" @@ -0,0 +1,44 @@ +1.资源包安装与环境配置 +安装资源包: +部署 STM32F407-ATK-Explorer 开发资源包(含驱动、BSP支持包)。 +配置 QEMU 仿真环境(用于无硬件调试)。 +2.概念: + 临界区(Critical Section)定义:进程内访问共享资源的代码段,需通过关中断/信号量保护; + 线程状态机(就绪→运行→阻塞→挂起); +RT-Thread启动流程 +struct rt_thread { + void (*entry)(void*); // 入口函数指针 + void* parameter; // 传入参数 + rt_uint8_t* stack_addr; // 栈起始地址(静态分配时需显式指定) + rt_uint32_t stack_size; // 栈大小(单位:字节) + void* sp; // 栈顶指针(由rt_hw_stack_init()初始化) + rt_uint8_t init_priority; // 初始优先级(0最高) + rt_tick_t init_tick; // 时间片长度(tick数) + // ... 其他状态字段 +}; + 内核开发指令: +LDR 从内存加载数据至寄存器 +STR 寄存器值存入内存 +ADD 寄存器算术运算 +BL 带链接跳转(保存返回地址) +PUSH 寄存器入栈 + 线程 + 线程本质:可被调度的执行流,其运行状态由线程控制块(TCB) 维护。 + 线程创建双模式: +// 静态创建(栈内存由用户预分配) +rt_err_t rt_thread_init(rt_thread_t thread, + const char* name, + void (*entry)(void*), + void* parameter, + void* stack_start, + rt_uint32_t stack_size, + rt_uint8_t priority, + rt_uint32_t tick); + +// 动态创建(内核自动分配TCB及栈) +rt_thread_t rt_thread_create(const char* name, + void (*entry)(void*), + void* parameter, + rt_uint32_t stack_size, + rt_uint8_t priority, + rt_uint32_t tick); \ No newline at end of file diff --git "a/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day3.md" "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day3.md" new file mode 100644 index 0000000000000000000000000000000000000000..4efd4d76063f9c1b319db42c1dbff01b1b1f1eca --- /dev/null +++ "b/2025/\347\254\2546\347\273\204(GD32F527I-EVAL)/\344\270\201\345\223\262\347\277\224/\347\254\224\350\256\260/day3.md" @@ -0,0 +1,82 @@ +定时器链表操作机制 +定时器系统通过周期性中断在固定时间间隔内轮询检查所有线程的定时器状态。每个线程维护一个独立的线程定时器结构,记录其累积运行时间。当某线程的运行时间超过预设阈值时,系统将触发超时处理函数。为高效管理这些定时器,系统采用双向链表组织所有线程定时器:链表头部指向活跃定时器的首节点,每个节点包含线程控制块指针、剩余时间计数值及链表指针。定时器检查时,从链表头开始遍历,逐个递减计数值并判断超时条件,确保检查操作的时间复杂度为O(n),同时支持动态添加或移除定时器节点。 + +线程间通信(IPC)机制 +线程间通信的核心作用在于实现线程同步与数据交换,具体包括: + +互斥操作:通过关中断或同步原语确保临界区访问的排他性。 +休眠-唤醒机制:利用等待队列实现线程阻塞与唤醒。 +关键约束: +全局变量不可直接用作IPC媒介,因其无法解决竞态条件、缓存一致性及原子性问题,易导致数据损坏或逻辑错误。必须采用内核提供的同步原语保障通信可靠性。 + +通信机制一:消息队列 +消息队列由固定数量的消息块组成,每个消息块存储固定长度的数据。初始化时需指定消息块数量及单个消息块大小。 + +写操作(发送消息): +有空闲空间:立即写入,返回成功。 +无空闲空间: +若线程选择阻塞:将线程从就绪队列移除,加入队列的发送等待链表(Send List),并启动超时定时器;唤醒条件为: +其他线程执行读操作释放空间; +定时器超时,返回错误码。 +若线程选择非阻塞:直接返回错误码。 +读操作(接收消息): +有可用数据:立即读取,返回成功。 +无可用数据: +若线程选择阻塞:将线程从就绪队列移除,加入队列的接收等待链表(Receive List),并启动超时定时器;唤醒条件为: +其他线程执行写操作填入数据; +定时器超时,返回错误码。 +若线程选择非阻塞:直接返回错误码。 +唤醒机制: +队列内部维护两个独立等待链表(Send List 和 Receive List)。当数据写入时,系统遍历Receive List唤醒首个等待线程;当数据读出时,遍历Send List唤醒首个等待线程。多线程竞争时,支持FIFO(先入先出)或优先级排序策略。数据存储遵循"写入队尾,读取队首"原则,确保有序性。 + +通信机制二:邮箱 +邮箱专为高效传递小规模数据(通常为整型值)设计,结合环形缓冲区、等待链表及超时定时器实现。 + +读操作: +有数据:直接读取缓冲区首个值,返回成功。 +无数据: +若线程选择阻塞:将线程加入邮箱的接收等待链表,并启动超时定时器;唤醒条件为: +其他线程写入数据; +定时器超时,返回错误码。 +若线程选择非阻塞:直接返回错误码。 +写操作: +有空位:直接写入环形缓冲区,返回成功。 +无空位: +若线程选择阻塞:将线程加入邮箱的发送等待链表,并启动超时定时器;唤醒条件为: +其他线程读取数据释放空间; +定时器超时,返回错误码。 +若线程选择非阻塞:直接返回错误码。 +典型实现中,邮箱缓冲区大小固定(如5个unsigned long槽位),通过环形索引管理数据存取,避免链表操作开销,提升小数据传递效率。 + +信号量(Semaphore) +信号量用于抽象化CPU或硬件资源的可用数量,其核心结构包含计数值(value)及等待线程链表。 + +获取资源(P操作): +value > 0:立即递减值,线程继续执行。 +value = 0: +若线程选择阻塞:从就绪队列移除,加入信号量等待链表,并启动超时定时器;唤醒条件为: +其他线程释放资源(value > 0); +定时器超时,返回错误码。 +若线程选择非阻塞:直接返回错误码。 +释放资源(V操作): +递增value,若等待链表非空则唤醒首个线程。 +局限性: + +任意线程均可执行V操作,存在资源误释放风险; +可能引发优先级反转问题(高优先级线程因等待低优先级线程持有的资源而阻塞)。 +互斥量(Mutex) +互斥量是专为互斥访问设计的特殊信号量,核心改进在于: + +优先级继承机制:当高优先级线程等待互斥量时,持有者线程优先级临时提升至等待者优先级,避免优先级反转;释放后恢复原优先级。 +所有权约束:仅持有互斥量的线程可执行释放操作,防止误释放。 +递归持有支持:同一线程可多次获取互斥量,内部通过持有计数(hold)跟踪嵌套深度,需等量释放。 +结构体包含关键字段:value(资源状态)、owner(持有线程指针)、original_priority(持有者原始优先级)、hold(持有计数)。 + +事件组(Event Group) +事件组用于实现"等待多个事件"的同步模式,与前述机制的区别在于: + +队列:传递任意大小数据块,适用于大数据传输。 +邮箱:传递固定长度整型数据,适用于小数据高效传输。 +信号量:表示资源实例数量,不携带数据。 +互斥量:专为互斥访问优化,具备优先级继承和所有权机制。 +事件组:通过位掩码聚合多个事件标志,线程可等待特定组合事件(如"事件A与事件B同时发生"或"事件A或事件B任一发生"),实现复杂同步场景。 \ No newline at end of file