Linux--测试信号阻塞及排队

本文深入探讨了不可靠信号和可靠信号在程序中的处理机制。不可靠信号如SIGQUIT,在被阻塞时会放入缓冲区,可能丢失;而可靠信号如SIGRTMIN,则支持排队不丢失。文章通过代码示例展示了两种信号的阻塞与非阻塞状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

不可靠信号

不可靠信号在被阻塞时,程序是不会响应信号处理的。这并不是说程序没收到信号,而是程序把接收到的信号放到了缓冲区,一旦该信号解除阻塞则会立即被发送一次(不可靠信号会丢失),之后程序可以正常响应信号处理。

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

void sig_usr(int signal)
{	
	if (signal == SIGQUIT)
	{
		printf("Received SIGQUIT signal!\n");
	}
}
int main()
{
	struct sigaction act;
	act.sa_handler = sig_usr;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaddset(&act.sa_mask, SIGQUIT); 		//添加SIGQUIT到信号集
	if (sigaction(SIGQUIT, &act, NULL) < 0) //设置SIGQUIT信号处理方式
	{
		printf("sigaction act error.\n");
		return -1;
	}
	printf("SIGQUIT signal blocked\n");
	sigprocmask(SIG_BLOCK, &act.sa_mask, NULL); 	//阻塞信号集
	sleep(10);
	printf("SIGQUIT signal unblocked\n");
	sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL);	//非阻塞信号集
	sleep(10);
	sleep(10);

	return 0;
}

在这里插入图片描述


可靠信号

可靠信号在被阻塞时,程序也是不会响应信号处理的。程序同样把接收到的信号放到了缓冲区,一旦该信号解除阻塞则会立即被发送,不同于不可靠信号的是可靠信号支持排队不丢失,缓存了几个信号就会被发送几次,之后程序同样可以正常响应信号处理。

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

void sig_usr(int signal)
{	
	if (signal == SIGRTMIN)
	{
		printf("Received SIGRTMIN signal!\n");
	}
}
int main()
{
	struct sigaction act;
	act.sa_handler = sig_usr;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaddset(&act.sa_mask, SIGRTMIN); 			 //添加SIGRTMIN信号到信号集
	if (sigaction(SIGRTMIN, &act, NULL) < 0)	 //设置SIGRTMIN信号处理方式
	{
		printf("sigaction act error.\n");
		return -1;
	}
	printf("SIGRTMIN signal blocked\n");
	sigprocmask(SIG_BLOCK, &act.sa_mask, NULL);  //阻塞信号集
	sleep(30);
	printf("SIGRTMIN signal unblocked\n");
	sigprocmask(SIG_UNBLOCK, &act.sa_mask, NULL);//非阻塞信号集
	sleep(10);
	sleep(10);

	return 0;
}

在这里插入图片描述


参考网址: http://www.cnblogs.com/encode/archive/2012/06/13/2547493.html

<think>嗯,用户想比较FreeRTOS和Linux信号量的原理差异。这个问题涉及嵌入式实时系统和通用操作系统的内核机制,需要从设计目标、实现方式和行为特征三个维度展开。 用户可能是嵌入式开发工程师,正在做系统选型或移植工作。ta特意强调"principle comparison",说明需要理论层面的深度对比而非简单功能列表。考虑到FreeRTOS常用于资源受限环境,而Linux信号量支持更复杂的场景,这个比较对ta的架构设计应该很关键。 先从设计哲学切入:FreeRTOS作为RTOS核心诉求是确定性,其信号量设计完全服务于可预测的实时响应;Linux作为通用OS则优先考虑吞吐量和公平性。这导致底层实现差异——FreeRTOS用轻量级任务阻塞队列,Linux则依赖更复杂的等待队列和自旋锁保护。 行为差异点要重点说明优先级反转问题。虽然两者都支持优先级继承,但FreeRTOS的xSemaphoreCreateMutex()默认开启继承,而Linux需要显式设置PTHREAD_PRIO_INHERIT属性。这个细节在跨系统移植时容易出错。 测试用例的设计思路可能对用户更有启发:通过创建高低优先级任务竞争信号量的场景,用示波器抓取实际响应时间差异。可以补充说明FreeRTOS的vApplicationMallocFailedHook()钩子函数在调试信号量分配失败时特别有用。 最后要注意术语统一。比如Linux的"任务"应表述为"进程/线程",避免用户混淆。二进制信号量在FreeRTOS叫Semaphore,在Linux则对应sem_t,这些命名差异需要明确标注。</think>FreeRTOS 和 Linux信号量在核心原理上相似,都是基于 **计数器** 的同步机制,用于任务/进程间的互斥与同步。但受各自操作系统设计目标(实时性 vs 通用性)和运行环境(资源受限 vs 资源丰富)影响,在实现细节、行为特性和 API 上存在显著差异。以下是详细对比: --- ### **核心原理共性** 1. **计数器基础**: * 两者都维护一个整数值(计数器)。 * **`give/post`** 操作:递增计数器,唤醒等待者。 * **`take/wait`** 操作:尝试递减计数器。若计数器 > 0,则成功递减并返回;若计数器 = 0,则调用者阻塞(可选择超时)。 2. **同步与互斥**: * 都可用于: * **资源管理**(计数信号量):计数器初始值 = 可用资源数。 * **任务同步**(二进制信号量):计数器初始值 = 0 或 1,表示事件是否发生。 * **互斥访问**(互斥锁):特殊二进制信号量,支持优先级继承/置顶(解决优先级反转)。 --- ### **核心差异** | 特性 | FreeRTOS 信号量 | Linux 信号量 (`semaphore.h`) | Linux POSIX 信号量 (`semaphore.h`) | | :------------------ | :----------------------------------------------- | :----------------------------------------------- | :----------------------------------------------- | | **设计目标** | **实时性、确定性、低开销** (资源受限嵌入式系统) | **通用性、公平性、丰富功能** (多用户、多进程系统) | 符合 POSIX 标准,跨平台一致性 | | **实现基础** | 轻量级队列(阻塞任务链表) | 内核对象,关联`wait_queue`和自旋锁 | 内核对象,关联`wait_queue`和自旋锁 | | **阻塞行为** | **任务**阻塞信号量队列。优先级决定唤醒顺序。 | **进程/线程**阻塞在内核等待队列。默认 FIFO,可配置优先级。 | **进程/线程**阻塞在内核等待队列。默认 FIFO。 | | **阻塞上下文限制** | **禁止在中断服务程序(ISR)中阻塞**。提供 `xSemaphoreTakeFromISR()` 用于非阻塞尝试。 | 可在**进程上下文**阻塞。**中断上下文禁止阻塞**。 | 同 Linux Kernel Semaphore。 | | **API 特性** | API 区分**二进制信号量**、**计数信号量**、**互斥锁**。互斥锁有优先级继承机制。 | 单一 `struct semaphore` 类型,通过初始值区分用途(计数/二进制)。无内置优先级继承。 | `sem_t` 类型。提供命名信号量用于进程间同步。支持 `sem_timedwait()`。 | | **优先级反转解决** | **互斥锁(`xSemaphoreCreateMutex()`)** 默认支持优先级继承 (`configUSE_MUTEXES=1`)。 | **原生支持优先级继承**。需使用 RT-Mutex 或其他机制。 | **可选支持** (`PTHREAD_PRIO_INHERIT`)。 | | **所有权概念** | **仅互斥锁**有所有权概念(哪个任务持有)。信号量无此概念。 | 无原生所有权概念(谁都可以 `up`)。 | 无原生所有权概念(谁都可以 `sem_post`)。 | | **中断安全 API** | 提供 `xSemaphoreGiveFromISR()`, `xSemaphoreTakeFromISR()` 及配套 `pxHigherPriorityTaskWoken` 机制。 | 提供 `down_trylock()`, `up()` **可在中断上下文调用**(非阻塞)。 | **无标准 ISR 安全 API**。 | | **资源消耗** | **极低**(数据结构简单,无复杂调度开销)。 | 相对较高(关联内核复杂数据结构)。 | 相对较高。 | | **使用场景侧重** | 硬实时任务同步、资源管理、临界区保护。 | 驱动开发、内核同步、简单的进程/线程同步。 | 用户空间进程/线程同步(命名信号量支持 IPC)。 | --- ### **关键差异详解** 1. **实时性与阻塞行为**: * FreeRTOS:阻塞的任务按**优先级**排序在等待队列中。当信号量可用时,**最高优先级**的等待任务被唤醒。这确保了高优先级任务的**低延迟响应**,是实时性的核心[^1]。 * Linux:默认等待队列是 **FIFO**。虽然某些配置(如 `CONFIG_SEMAPHORE_SLEEPERS`) 或 RT-Mutex 可支持优先级排队,但标准信号保证最高优先级任务优先获取。更注重公平性而非实时性[^2]。 2. **中断上下文处理**: * FreeRTOS:严格区分任务和 ISR。ISR **绝阻塞**。专用 `FromISR` API 用于在 ISR 中非阻塞地操作信号量,并通过 `pxHigherPriorityTaskWoken` 提示是否需要上下文切换(在退出 ISR 前可能执行)[^3]。 * Linux:`up()` 可在中断上下文安全调用(非阻塞)。`down_trylock()` 也可在中断上下文使用。但阻塞操作(`down()`)只能在进程上下文调用。 3. **互斥锁与优先级继承**: * FreeRTOS:明确区分 `xSemaphoreCreateMutex()`(互斥锁)和 `xSemaphoreCreateBinary()`(二进制信号量)。**互斥锁内置优先级继承机制**,是保护共享资源的首选,能有效缓解优先级反转问题[^4]。 * Linux Kernel Semaphore:单一类型。**原生支持优先级继承**。用作互斥锁时,需开发者自行注意优先级反转风险,或使用专门支持优先级继承的 `rt_mutex`。 * Linux POSIX Semaphore:通过设置线程属性 `PTHREAD_PRIO_INHERIT` 可让基于它的互斥锁支持优先级继承,但这属于 POSIX 线程特性,非信号量本身特性。 4. **所有权**: * FreeRTOS 互斥锁:持有任务“拥有”锁。只有持有者才能释放它(`xSemaphoreGive()`)。这防止了误释放。 * Linux Semaphore:无所有权概念。任何线程/进程都可以对信号量执行 `up()`/`sem_post()`,即使它没有执行过 `down()`/`sem_wait()`。这更灵活但也更易出错(如误释放)。 5. **API 设计哲学**: * FreeRTOS:API 直接、明确区分类型(`CreateBinary`, `CreateCounting`, `CreateMutex`),参数少,行为清晰。强制开发者思考所需语义。 * Linux:Kernel API (`down`, `up`) 简洁但语义相对单一(计数信号量)。POSIX API (`sem_wait`, `sem_post`) 标准统一但需要额外初始化 (`sem_init`/`sem_open`)。 --- ### **总结** * **原理核心相同**:都是基于计数器的 `take/wait` (P) 和 `give/post` (V) 操作。 * **差异源于设计目标**: * **FreeRTOS 信号量**:为**实时性、确定性和最小开销**优化。体现在优先级唤醒、严格的 ISR API、内置优先级继承的互斥锁、明确区分的信号量类型。 * **Linux 信号量**:为**通用性、功能丰富性和公平性**设计。体现在更复杂的底层实现、FIFO 倾向、无内置优先级继承、无所有权、支持命名信号量(POSIX IPC)。 * **选择关键**: * 在 **硬实时嵌入式系统** 中,优先使用 FreeRTOS 信号量(特别是互斥锁用于资源保护)。 * 在 **Linux 内核驱动开发** 中,使用 Kernel Semaphore 或更高级的同步原语(如 completions, mutexes with PI)。 * 在 **Linux 用户空间多线程/多进程应用** 中,使用 POSIX 信号量(或更高级的 pthread mutex/condvar)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值