使用SIGUSR1、SIGUSR2信号传字符串时服务器无法处理大量字符问题
问题根因分析
- 核心原因是标准Unix信号不支持排队,同一时间多个同类型信号送达时只会保留1个,发送速度过快就会出现信号丢失,最终导致乱码、双方互相等待卡住。
- 客户端代码存在两处关键隐患:
sending_bits函数中g_recieve为0时进入空转死循环,没有主动阻塞等待信号,不仅占满CPU导致调度优先级降低,还会疯狂发送信号引发丢包- 全局标记
g_recieve没有加volatile修饰,编译器可能优化掉变量的实时读取,导致信号处理函数修改了标记后主逻辑仍读取旧值死等
- 你之前注释掉了
usleep逻辑,相当于完全没有限制发送速率,信号发送速度远快于服务器处理速度,必然出现丢信号的问题
更稳妥的修复方案
你当前用sleep(5)加调高usleep参数的方案属于临时 workaround,实际可以用更高效可靠的方式修复,不需要固定等待时长:
- 给全局标记加
volatile修饰,避免编译器优化:
volatile int g_recieve;
- 在
sending_bits函数中g_recieve置为0后调用pause()主动阻塞,直到收到服务器的确认信号再继续执行,替换原来的空转逻辑:
void sending_bits(char c, int pid) { int i; i = 128; while(i >= 1) { if (g_recieve == 1) { if (i & c) { if (kill(pid, SIGUSR1) == -1) errors("Error in sending signal!\n"); } else { if (kill(pid, SIGUSR2) == -1) errors("Error in sending signal!\n"); } i /= 2; g_recieve = 0; } else { // 主动阻塞等待确认信号,不占用CPU pause(); } } }
- 不需要额外加
usleep限制速率,停等逻辑本身就保证了发一个位等一个确认,不会出现信号堆积丢包,传输效率比加固定sleep高很多。
内容的提问来源于stack exchange,提问作者Makar
相关产品推荐
相关产品推荐

