信号(signal)
来源:互联网 发布:淘宝网乌梢蛇木瓜丸 编辑:程序博客网 时间:2024/05/16 07:54
信号(signal)
信号是什么?信号非常常见,上课铃声,红绿灯,鸣笛等都是信号。操作系统中也有信号,为什么操作系统要设置信号,这是为了保护操作系统,防止用户进行操作时,采取了某些办法,导致系统软硬件出现异常。
那么信号如何产生
- 键盘。在linux操作系统下,通过ctrl+c,ctrl+z等组合键可以产生信号。
- 通过输入kill命令。linux下,通过命令行输入kill -sig pid可以向操作系统的某个pid进程发送sig号的信号。例如:kill -9 2955
这里有一个test的进程在运行,发送kill -9 2955后进程被终止。 - 软硬件发送信号。某些操作可能导致软硬件出现错误,于是会通过操作系统向用户发送信号。
- 库函数kill()函数。不做详细解释
本节主要讲信号的操作,不对信号的产生,收信号做详细的解释。
信号操作
信号集就是pcb中信号的字段,用位图来表示。
int sigemptyset(sigset_t *set);//初始化信号集为空int sigfillset(sigset_t *set);//充满信号集int sigaddset(sigset_t *set, int signo);//添加信号int sigdelset(sigset_t *set, int signo);//解除信号int sigismember(const sigset_t *set, int signo);//查看信号是否在信号集中存在
这些函数都是用户上的函数,真正阻塞系统信号的是sigprocmask();
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);//how,*set设为修改的信号集,*oset,旧的信号集(未修改的)
how三种方式:
- SIG_BLOCK,设置为阻塞方式。
- SIG_UNBLOCK,解除阻塞信号。
SIG_SETMASK,设置当前信号字为set所指的值。
sigpending
int sigpending(sigset_t *set);
sigpending读取当前进程的未决信号集,通过set参数传出。调⽤用成功则返回0,出错则返回-1。
下面为信号屏蔽与解除的示例:
#include <signal.h>#include <stdlib.h>void printsigset(sigset_t *nset){ int i = 1; for(;i<32;i++) { if(sigismember(nset,i)) { printf("1"); } else { printf("0"); } } printf("\n");}int main(){ sigset_t nset,oset; sigemptyset(&nset); sigemptyset(&oset); sigaddset(&nset,2); sigprocmask(SIG_SETMASK,&nset,&oset); while(1) { sigpending(&nset); printsigset(&nset); sleep(1); } return 0;}
这段代码给信号集加入了2号信号,如果收到2号打印1,没有打印0.
下面编写了一个mysleep函数模拟实现sleep函数。
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <sys/types.h>#include <unistd.h>void handler(int sig){}int mysleep(int timeout){ struct sigaction nset,oset; nset.sa_flags = 0; nset.sa_handler = handler; sigemptyset(&nset.sa_mask); sigaction(SIGALRM,&nset,&oset); alarm(timeout); pause(); sigaction(SIGALRM,&oset,NULL);}int main(){ while(1) { printf("hello world\n"); mysleep(1); } return 0;}
这段代码通过调用pause进程挂起,捕捉到信号错误返回,与alarm闹钟函数结合模拟实现。
这段代码还有很大问题,当alarm函数完成后,进程切出去执行别的进程而没有被挂起,闹钟响后,将会持续保持pause状态,而一直运行。
解决办法是:
屏蔽alarm信号,调用sigsuspend(sigset_t *set)函数实现pause与解除信号的原子性。
#include <stdio.h>#include <stdlib.h>#include <signal.h>#include <sys/types.h>#include <unistd.h>void handler(int sig){}int mysleep(int timeout){ struct sigaction nset,oset; sigset_t oldset,newset,susp; sigemptyset(&newset); sigaddset(&newset,SIGALRM); sigprocmask(SIG_BLOCK,&newset,&oldset); nset.sa_flags = 0; nset.sa_handler = handler; sigemptyset(&nset.sa_mask); sigaction(SIGALRM,&nset,&oset); alarm(timeout); susp = oldset; sigdelset(&susp,SIGALRM); sigsuspend(&susp); sigaction(SIGALRM,&oset,NULL); int ret = alarm(0); return ret;}int main(){ while(1) { printf("hello world\n"); mysleep(1); } return 0;}
信号屏蔽与解除与上述示例。
0 0
- 信号(signal)介绍
- 信号(signal)
- 信号(signal)介绍
- 信号(signal)介绍
- linux信号(signal)
- Linux信号(Signal)
- 信号(signal)
- linux信号(signal)
- linux 信号(signal)介绍
- 软中断信号(signal)
- Linux 信号signal(一)
- signal信号
- 信号signal
- 信号signal
- 信号signal
- 信号Signal
- 信号(SIGNAL)与槽(SLOT)
- UNIX平台信号(SIGNAL)处理
- Linux NFS服务器的安装与配置
- git 创建一个新branch,push到远端后,通过网页可以看到新建的branch
- AndroidStudio 对于library工程生成的jar包路径
- emboss 安装使用
- cas 使用 http协议
- 信号(signal)
- Design库中的控件之FloatingActionButton
- 欢迎您在新浪博客安家
- 华为李航:NLP 有 5 个基本问题,深度学习有4个做得很好
- Mvc 5和Redis实现自定义会话提供程序
- 学习JAVA第一周,三个数比较大小。
- RocketMQ
- 卡片
- hlog 详解