

# 信号

> 信号就像⼀个紧急电话。如果你想让你的朋友注意到某件重要的事情，可以打电话通知他。朋友接到电话（信号）后，便可以⽴即采取⾏动或处理相关事宜。  

## 信号的⼯作机制

- 发送信号：线程可以向另⼀个线程发送信号。可以让⽬标线程⽴即中断当前⼯作，转⽽处理信号事件。

- 处理信号：⽬标线程需要先安装信号处理函数，收到信号时会执⾏相应的处理操作

  <img src="https://typora-write.oss-cn-beijing.aliyuncs.com/20250211172815825.png" alt="信号相关接口" style="zoom:150%;" />

> ### 1. **rt_sem_create**
>
> 用于动态创建信号量。
> ```c
> rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag);
> ```
> #### 参数说明：
> - `name`：信号量的名字（可以为 `RT_NULL` 表示匿名信号量）。
> - `value`：信号量的初始值，表示信号量当前持有的资源数量（例如初始值为 0 表示等待事件，为 1 表示互斥量，或者更大值表示资源计数）。
> - `flag`：
>   - `RT_IPC_FLAG_PRIO`：优先级等待方式，等待线程按照优先级顺序排列。
>   - `RT_IPC_FLAG_FIFO`：先入先出等待方式，等待线程按照进入顺序排列。
> #### 返回值：
> - 成功：返回信号量的句柄 `rt_sem_t`。
> - 失败：返回 `RT_NULL`。
> #### 示例：
> ```c
> /* 创建一个初始值为 0 的信号量，用于同步场景 */
> rt_sem_t sync_sem = rt_sem_create("sync_sem", 0, RT_IPC_FLAG_PRIO);
> ```
> ### 2. **rt_sem_init**
> 用于静态信号量的初始化，一般用于静态分配内存的场景。
> ```c
> rt_err_t rt_sem_init(rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag);
> ```
> #### 参数说明：
>
> - `sem`：信号量对象的指针（需要预先定义好该信号量结构体）。
> - `name`：信号量的名字。
> - `value`：信号量的初始值。
> - `flag`：IPC 对象的属性标志（同 `rt_sem_create`）。
> #### 返回值：
> - 成功：返回 `RT_EOK`。
> - 失败：返回相应的错误代码。
> #### 示例：
> ```c
> /* 静态信号量定义 */
> static struct rt_semaphore static_sem;
> /* 静态信号量初始化，初始值为1，用于互斥操作 */
> rt_sem_init(&static_sem, "static_sem", 1, RT_IPC_FLAG_PRIO);
> ```
> ### 3. **rt_sem_take**
> 用于获取信号量，线程会尝试获取信号量，如果信号量的计数值为 0，线程会进入等待状态，直到信号量被释放或超时。
> ```c
> rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time);
> ```
> #### 参数说明：
>
> - `sem`：信号量的句柄。
> - `time`：超时时间（单位为系统 tick），表示最大等待时间。如果设置为 `RT_WAITING_FOREVER`，线程会一直等待。
> #### 返回值：
> - 成功：返回 `RT_EOK`。
> - 失败：返回 `-RT_ETIMEOUT`（超时）或其他错误代码。
> #### 示例：
> ```c
> /* 线程1等待信号量，直到收到信号 */
> rt_sem_take(sync_sem, RT_WAITING_FOREVER);
> ```
> ### 4. **rt_sem_release**
> 用于释放信号量，增加信号量的计数值，并唤醒等待该信号量的线程。
> ```c
> rt_err_t rt_sem_release(rt_sem_t sem);
> ```
> #### 参数说明：
> - `sem`：信号量的句柄。
>
> #### 返回值：
> - 成功：返回 `RT_EOK`。
> - 失败：返回相应的错误代码。
>
> #### 示例：
>
> ```c
> /* 线程2完成任务后释放信号量，通知线程1 */
> rt_sem_release(sync_sem);
> ```
> ### 5. **rt_sem_delete**
>
> 用于删除动态信号量（仅限于 `rt_sem_create` 创建的动态信号量）。
> ```c
> rt_err_t rt_sem_delete(rt_sem_t sem);
> ```
> #### 参数说明：
> - `sem`：信号量的句柄。
> #### 返回值：
> - 成功：返回 `RT_EOK`。
> - 失败：返回相应的错误代码。
> #### 示例：
> ```c
> /* 删除动态创建的信号量 */
> rt_sem_delete(sync_sem);
> ```



```
/*
 * Copyright (c) 2006-2025, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2025-02-06     RT-Thread    first version
 */

#include <rtthread.h> // 包含RT-Thread的核心头文件

#define DBG_TAG "main"    // 定义日志标签
#define DBG_LVL DBG_LOG   // 定义日志级别为普通日志
#include <signal.h>       // 包含POSIX信号头文件，用于信号处理
#include <rtdbg.h>        // 包含调试日志的头文件

static rt_thread_t thread1; // 定义线程1的句柄

// 线程1的信号处理函数
void thread_signal_handler(int signal)
{
    // 打印接收到的信号编号
    rt_kprintf("线程1进入信号处理函数处理任务，收到信号:%d...\n", signal);
    // signal.h文件中定义了SIGUSR1为30（用户定义信号1）
}

// 线程1的入口函数
void thread_entry1(void *parameter)
{
    // 安装信号处理函数
    rt_signal_install(SIGUSR1, thread_signal_handler);

    // 解除信号阻塞，使线程能够接收信号
    rt_signal_unmask(SIGUSR1);

    // 打印日志：线程1等待信号
    rt_kprintf("线程1等待信号...\n");

    // 无限循环
    while (1)
    {
        // 打印日志：线程1正在处理日常任务
        rt_kprintf("线程1正在处理日常任务...\n");

        // 线程延迟500毫秒
        rt_thread_mdelay(500);
    }
}

// 主函数
int main(void)
{
    // 创建线程1
    // 参数说明：
    // "thread1": 线程名称
    // thread_entry1: 线程入口函数
    // RT_NULL: 线程参数
    // 1024: 线程栈大小（单位：字节）
    // 10: 线程优先级（数值越小，优先级越高）
    // 10: 线程时间片
    thread1 = rt_thread_create("thread1", thread_entry1, RT_NULL, 1024, 10, 10);

    // 如果线程1创建成功，则启动线程1
    if (thread1 != RT_NULL)
    {
        rt_thread_startup(thread1);
    }

    // 主线程延迟2000毫秒
    rt_thread_mdelay(2000);

    // 向线程1发送SIGUSR1信号
    rt_thread_kill(thread1, SIGUSR1);

    // 主函数返回0，表示正常结束
    return 0;
}
```
实现效果：
![image-20250207184238465](https://typora-write.oss-cn-beijing.aliyuncs.com/20250211172822967.png)

**遇到的问题：**

如果不在内核中进行使能，则使用信号的相关函数会报错

![image-20250207183417071](https://typora-write.oss-cn-beijing.aliyuncs.com/20250211172830480.png)