做网站需要数据库么,18款禁用软件app网站入口,论坛营销的推广方法,上海市建设工程检测网#include signal.h
信号signal#xff1a;Linux或Unix系统支持的经典的消息机制#xff0c;用于处置进程#xff0c;挂起进程或杀死进程
kill -l #查看系统支持的信号 1~31 Unix经典信号#xff08;软件开发工程师#xff09;
32、33信号被系统隐藏#xf…#include signal.h
信号signalLinux或Unix系统支持的经典的消息机制用于处置进程挂起进程或杀死进程
kill -l #查看系统支持的信号 1~31 Unix经典信号软件开发工程师
32、33信号被系统隐藏不对用户开放供NPTL线程库使用
34~64 自定义信号/实时信号驱动工程师
CtrlC 系统帮你发送了 2)SIGINT信号。终端组合按键产生的信号杀死唯一的前台终端进程。 一、系统中触发信号的几种方式
1、终端组合按键触发信号
CtrlC SIGINT/2 终止进程 Ctrl\ SIGQUIT/3 退出进程 CtrlZ SIGTSTP/20 挂起终端进程
jobs #查看挂起的作业编号
fg 作业编号 #唤醒到前台 tty 终端 pts 虚拟终端 D (TASK_UNINTERRUPTIBLE) 不可中断的睡眠状态 R (TASK_RUNNING) 正在运行或在队列中的进程 S (TASK_INTERRUPTIBLE) 可中断的睡眠状态 T (TASK_STOPPED) 停止状态 t (TASK_TRACED) 被跟踪状态 Z (TASK_DEAD - EXIT_ZOMBIE) 退出状态但没被父进程收尸成为僵尸状态 W 进入内存交换从内核2.6开始无效 X (TASK_DEAD - EXIT_DEAD) 退出状态进程即将被销毁 高优先级 N 低优先级 L 有些页被锁进内存 s 包含子进程 位于前台的进程组 l 多线程克隆线程 multi-threaded (using CLONE_THREAD, like NPTL pthreads do) 2、命令触发信号
kill -signo信号 pid进程号 #向任意进程发送任意信号
3、函数触发信号
kill(pid_t pid,int signo); //向任意进程发送任意信号
raise(int signo); //向当前进程发送任意信号
abort(); //向当前进程发送固定的SIGABRT/6信号
#include stdio.h
#include stdlib.h
#include unistd.h
#include signal.hint main(int argc,char* argv[]){//支持命令KILL signo pidif(argc3){printf(pram error\n);exit(0);}kill(atoi(argv[2]),atoi(argv[1]));return 0;
}4、硬件异常产生信号
违规访问使用硬件导致信号杀死进程
1如果进程非法操作内存系统向其发送SIGSEGV/11杀死进程错误信号为段错误 char* strhello;str[0]H; //只读内存的写操作 2如果进程出现cpu运算异常系统向其发送SIGFPE/8杀死进程错误为浮点数例外 int b0; int a8/b; //除0
3如果进程出现内存访问越界系统向其发送SIGBUS/7杀死进程错误为总线错误 int* ptrNULL;int fdopen(MapFile,O_RDWR);int sizelseek(fd,0,SEEK_END);ptrmmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); //在使用mmap内存映射时,若MapFile是内容为空的新文件大小为0,没有与之对应的合法的物理页,mmap不能扩展发生了越界访问//添加错误检测来防止总线错误if((ptrmmap(NULL,size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0))MAP_FAILED){//内存映射perror(mmap failed);exit(0);}
5、软件异常产生信号
可以使用某个组件但是如果使用时触发软条件系统会杀死进程信号
1定时器alarm(10)定时到时系统向定时进程发送SIGALRM/14信号默认杀死进程 alarm(1); //定时1s后杀死进程,返回“闹钟”
2匿名管道读端关闭写端向管道写数据系统向写端发送SIGPIPE/13信号杀死进程 二、信号的三大行为与处理动作
信号的行为可以被修改默认情况下为默认行为但是可以改为忽略或捕捉三选一
1、默认行为SIG_DFL默认五种处理动作五选一
1TERM 直接杀死进程2CORE 杀死进程并且转储核心3STOP 挂起进程4CONT 忽略/继续进程5IGN 忽略
每个信号都有自己的默认动作来处置进程进程不是被挂起就是被杀死。只有动作为IGN的信号不会处置进程。
可以通过信号结束进程的输出分析其动作
2、忽略行为SIG_IGN忽略行为没有处理动作无法处置进程
3、捕捉行为SIG_ACTION可以手写捕捉函数来自定义行为
void sig_do(int n);
信号捕捉可以让自定义的捕捉函数与信号绑定以后触发此信号系统就会去执行此函数
可以用来设计实现条件触发的工作和任务信号触发则执行否则不执行。 修改信号行为
每个信号都有一个自己的信号行为结构体修改信号行为要保留其原结构体便于复位 struct sigaction nact,oact; //信号行为结构体act.sa_handlerSIG_DFL|SIG_IGN|函数指针;act.sa_flags0; //默认选项act.sa_mask; //临时屏蔽字sigaciton(signo,nact,oact); //替换信号行为结构体,act为新的,oact传出进程原有的
#include stdio.h
#include stdlib.h
#include unistd.h
#include signal.hvoid sig_do(int n){printf(已经成功捕捉SIGINT,signo%d\n,n);
}int main(){//void(*sa_handle)(int)struct sigaction act,oact;act.sa_handlersig_do;act.sa_flags0;sigemptyset(act.sa_mask);//初始化sigaction(SIGINT,act,oact);//替换信号行为while(1)sleep(1);return 0;
} 三、三种让信号生效的方法
1、信号忽略将信号设置为忽略行为
2、信号捕捉对信号进行捕捉设定绑定捕捉函数
3、信号屏蔽阻塞信号的传递 如果信号通过未决信号集系统会将未决中对应的位设置为1标记未决同时避免相同的信号同时处理。
如果未决为1对应的信号直接丢弃不处理
信号的处理不支持排队经典信号不支持排队队列但是自定义信号可以最大处理1个
驱动开发软件需要支持排队因为每个信号与功能绑定功能需要排队处理。经典信号目的是为了杀死进程处理一次即可无需排队。 信号通过屏蔽字从未决态切换为递达态系统将未决的1设置回0。系统会对正在处理的信号的屏蔽字临时设为1等待信号处理完将屏蔽字设回0避免如果捕捉函数中使用全局资源信号多次执行出现异常相同信号同时触发最大可以处理两个一个正在处理一个被屏蔽其他被丢弃。
如果将某个信号对应的屏蔽字位设置为1该信号被阻塞不允许递达。
用户可以自行设置信号屏蔽字实现阻塞信号的效果。
屏蔽方式与忽略与捕捉有很大的不同。忽略与捕捉吸纳后已经递达了并处理完成了但是屏蔽属于延迟处理信号没有消失。 信号屏蔽设置 sigset_t set; //信号集类型sigemptyset(set); //初始化0sigfillset(set); //初始化1sigaddset(set,signo); //将某个特定信号位置设置为1sigdelset(set,signo); //将某个信号位设置0int sigismember(set,signo); //返回特定信号位的位码sigprocmask(SIG_SETMASK,newset,oldset); //设置替换进程的信号屏蔽字
#includestdio.h
#includestdlib.h
#includeunistd.h
#includesignal.hint main(){sigset_t set,oset;sigemptyset(set);sigaddset(set,SIGQUIT);sigprocmask(SIG_SETMASK,set,oset);while(1)sleep(1);return 0;
}四、高级信号与普通信号
高级信号只要发出必然递达无法屏蔽捕捉忽略
SIGKILL/9 必然杀死
SIGSTOP/19 必然挂起
硬件异常的信号SIGSEGV SIGFPE SIGBUS用户发出触发可以屏蔽但是系统触发不可屏蔽 查看当前进程实时的信号情况应该查看未决信号集 sigpending(pset); //调用此函数系统会传出当前进程的未决信号集
#includestdio.h
#includestdlib.h
#includeunistd.h
#includesignal.hint main(){sigset_t set,oset,pset;sigemptyset(set);sigaddset(set,SIGINT);//2sigaddset(set,SIGQUIT);//3sigaddset(set,SIGSEGV);//11sigaddset(set,SIGALRM);//14sigprocmask(SIG_SETMASK,set,oset);while(1){sigpending(pset);//传出进程未决for(int signo1;signo32;signo)printf(%d,sigismember(pset,signo));printf(\n);sleep(1);}return 0;
} 信号的处理不是实时的
系统发出的信号在内核层而程序运行在用户层
1.进程执行于用户层串行执行主函数代码
2.信号发送到内核层等待处理
3.满足切换条件切换到内核层
触发上下文切换cpu权限切换的三种事件系统调用、软件中断时间片完、异常
4.完成调用、处置中断、处置异常
5.在返回用户层前检查是否有未递达信号如果有则处理
6.发现捕获函数在用户层使用系统使用指令直接执行捕捉函数避免切换执行捕捉函数系统并没有降低权限避免了开销
7.执行完毕通过SIG_RETURN指令返回内核层
8.执行上下文切换返回用户空间
9.主函数从暂停的位置继续执行 一般情况下主函数率先执行但是执行过程中触发信号系统调用捕捉函数捕捉函数永远比主函数先执行完
主函数运行时使用当前进程的时间片捕捉函数调用时主函数暂停使用当前进程的时间片一个进程的时间片资源只有一份