信号的阻塞处理案例

信号在几种情况下会进入阻塞状态,一是信号处理函数的执行过程中,该信号将被阻塞,直道信号函数执行完成,该阻塞将会解除。这种机制的主要作用是避免信号的嵌套;第二

中情况是通过sigaction进行信号安装时,如果设置了sa_mask阻塞信号集,则该信号集中的信号在信号处理函数被执行期间将会阻塞,还有另外一种情况下信号将会进入阻塞,

这就是通过系统调用sigpromask,可以通过该系统调用制定阻塞某个或者几个信号。第一种情况是系统自动阻塞的,后面两种情况是认为设置信号阻塞。

第二种情况是当信号处理函数正在执行过程,可能有其他的信号到来,此时,当前的信号处理函数就会被中断,而这往往是不希望发生的。此时可以通过sigaction系统调用的信号

阻塞掩码对相关信号进行阻塞,通过这种阻塞信号。在信号处理函数执行结束后就会接触。第三种情况较多:典型情况某个信号处理函数与程序代码都要对某个共享数据区进行读

写。如果进程收到了该信号,则程序的读写过程被中断而执行信号处理函数,而信号处理函数对该数据共享区进行读写,此时共享数据区就会发生混乱。这种情况下,需要在程序

读写发生混乱。这种情况下需要在读写共享区前阻塞信号,在读写完成后再接触信号阻塞。


#include <stdio.h>
#include <signal.h>
void handle_sigint(int signo)
{
    printf("receive signal %d\n",signo);
}
int main()
{
    sigset_t mask;//信号掩码结构变量,用于指定新的信号掩码
    sigset_t omask;//信号掩码结构题变量,用来保存原来的信号处理掩码
    signal(SIGINT,handle_sigint);//安装信号
    sigemptyset(&mask);//清空信号处理掩码
    sigaddset(&mask,SIGINT);//向掩码结构增加SIGINT
    sigprocmask(SIG_BLOCK,&mask,&omask);//设置掩码,设置完成SIGINT信号将被阻塞
    sleep(10);
    sigprocmask(SIG_SETMASK,&omask,NULL);//恢复原有的信号处理掩码
    return 0;
 
}


### 信号量集合导致阻塞的原理 信号量是一种用于控制并发访问共享资源的重要工具。当多个进程尝试访问同一组有限资源时,可能会发生竞争条件,从而引发死锁或阻塞的情况。具体来说,信号量集中的某个信号量可能因为其值不足以满足请求而导致阻塞。 #### 阻塞原因分析 1. **资源不足** 如果一个进程试图通过 `P` 操作减少信号量的值,而该信号量当前值已经为零,则此操作会被挂起并进入等待队列,直到另一个进程执行 `V` 操作增加信号量的值[^3]。 2. **计数限制** 对于普通信号量而言,由于其实现了计数功能,因此可能存在多个进程同时争夺相同数量的资源。一旦这些资源耗尽,后续请求将被迫排队等候释放资源的通知[^1]。 3. **错误配置** 创建信号量集时使用的参数不当也可能引起不必要的延迟甚至永久性的阻塞状态。例如,在调用 `semget()` 函数创建新的信号量实例时,如果没有正确设置 `semflg` 参数中的标志位(如 IPC_CREAT 或者 IPC_EXCL),可能导致意外行为或者失败返回码[^2]。 --- ### 解决方案探讨 为了有效应对由上述因素引起的阻塞现象,可以从以下几个方面入手: #### 资源管理优化 - 提前分配足够的初始资源给各个信号量对象,并确保它们在整个生命周期内的可用性始终维持在一个合理的水平上; - 定期监控系统运行状况以及各线程/进程间交互情况,及时调整相关参数以适应实际负载变化的需求。 #### 编程实践改进 - 使用超时机制防止无限期等待:许多操作系统都支持带有时限选项的操作函数版本(比如Linux下的 sem_timedwait),允许开发者设定最大容忍时间长度之后再决定是否继续重试还是采取其他措施退出循环逻辑处理流程之外; - 实施优先级继承策略(Priority Inheritance Protocol, PIP): 当高优先级任务因低优先级持有某临界区而受阻时自动提升后者临时级别直至完成整个事务过程结束恢复正常秩序为止. #### 错误预防手段 - 在初始化阶段仔细校验输入数据合法性尤其是涉及权限掩码部分的内容准确性验证工作必不可少 ; - 借助调试工具捕获潜在隐患所在位置进而修复漏洞缺陷提高软件健壮性和可靠性程度 . ```c #include <stdio.h> #include <sys/ipc.h> #include <sys/sem.h> union semun { int val; /* Value for SETVAL */ }; void initialize_semaphore(int sem_id){ union semun arg; arg.val = 1; // Set initial value to one resource available. if (semctl(sem_id, 0, SETVAL, arg) == -1){ perror("Failed initializing semaphore"); } } int main(){ key_t key = ftok("/tmp", 'A'); int semid = semget(key, 1, IPC_CREAT | 0666); if(semid != -1){ initialize_semaphore(semid); struct sembuf sops = {0,-1,SEM_UNDO}; printf("Attempting to acquire the semaphore...\n"); if(-1==semop(semid,&sops,1)){ perror("Error acquiring semaphore."); }else{ puts("Semaphore acquired successfully!"); sleep(5); // Simulate work being done sops.sem_op=+1; // Release the semaphore after completion of task. semop(semid,&sops,1); puts("Released semaphore."); } semctl(semid,0,IPC_RMID,NULL); // Clean up at exit. }else{ perror("Unable create/get semaphore ID."); } } ``` 以上代码片段展示了如何安全地获取和释放二元信号量,同时也包含了清理工作的示范。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值