洪洞网站建设谷歌搜索指数查询

当前位置: 首页 > news >正文

洪洞网站建设,谷歌搜索指数查询,怎么选择宜昌网站建设,遵义市做网站的电话一、信号介绍 什么是中断#xff1a; 当进程接收到消息后中止当前正在执行的任务#xff0c;转而执行其它任务#xff0c;等待其它任务执行完毕后再返回继续执行。这种执行模式称为中断#xff0c;分为硬件中断和软件中断两种
什么是信号#xff1a; 信号是UNIX、类UNI…一、信号介绍 什么是中断 当进程接收到消息后中止当前正在执行的任务转而执行其它任务等待其它任务执行完毕后再返回继续执行。这种执行模式称为中断分为硬件中断和软件中断两种
什么是信号 信号是UNIX、类UNIX以及其他POSIX兼容的系统中为了完成不同进程之间通讯的一种方式。是一种软中断是一种异步处理机制用于提醒进程某个事件发生了可能要去处理。 当一个信号发送给一个进程操作系统就会中断该进程的正常控制流程如果中断前预先设置过如何处理该信号(绑定过该信号的信号处理函数)那么中断后会执行该函数执行完返回中断点继续执行否则就按信号的默认处理方式进行

执行 kill -l 查看当前系统可以产生的所有信号

常见的信号 SIGINT2 Ctrlc 终止 SIGQUIT(3) Ctrl\ 终止core SIGFPE(8) 除0 终止core SIGSEGV(11) 段错误 终止core SIGTSTP(20) Ctrlz 暂停 SIGCONT(18) fg 继续 不可靠信号与可靠信号 不可靠信号 建立在早期信号处理机制上的信号被称为不可靠信号1-31 非实时信号不支持排队机制可能会丢失信号同一个信号产生多次进程可能只收到一次 当进程收到这类信号执行了第一次用户设置的信号处理函数后会还原会默认的处理方式。
可靠信号 位于34-64的信号是可靠信号 实时信号支持排队机制信号只要产生就必定会被处理因此不会丢失
信号的来源 硬件异常由硬件设备产生的信号例如除零、非法访问内存、总线错误、未定义指令 软件异常命令kill\函数产生信号
信号处理的默认动作 忽略 终止进程 终止并产生core文件 捕获并处理 二、捕获信号 #include signal.h ​ // 信号处理函数的格式 typedef void (*sighandler_t)(int); ​ sighandler_t signal(int signum, sighandler_t handler); 功能向内核注册一个信号和它的信号处理函数相当于捕获该信号绑定信号 signum信号码可以写整数值也可以用宏名 ​ 在某些UNIX系统中通过signal注册信号处理函数后只有一次有效后面会变回默认处理方式为了在这种系统中得到持久的信号绑定可以在信号处理函数的末尾再次通过signal重新注册一次 可以通过命令 kill 信号码 进程号 给该进程发送信号
练习测试一下哪些信号不可以被捕获处理 9和19号信号不能被忽略也不能被不能被捕获 普通用户只能给自己的进程发送信号只有root用户可以给任何进程发送信号 当信号处理完信号处理函数后是会回到产生信号的代码位置继续执行如果我们捕获并处理的是段错误\除零这种信号就会产生死循环因为这些错误并没有因为捕获了信号就消失而是一直存在并产生信号正确做法是在他们的信号处理函数中进行数据保存然后直接结束程序。exit()
三、发送信号的方式 键盘 给当前终端控制下的活跃进程发送信号 Ctrlc Ctrl\ Ctrlz fg
命令: kill -信号码 进程号 killall -信号码 进程名给所有的同名的进程发送信号 事件 当程序执行了某种非法操作被操作系统发现了操作系统会给进程发送对应的信号例如段错误、除零、总线错误、错误指令等。
函数 int kill(pid_t pid, int sig); 功能给指定的进程发送信号 pid:给进程号为pid的进程发送pid 0 给pid号进程发送信号sigpid 0 给同组的所有进程发送信号sigpid -1 给所有进程发送信号sig前提是有向该进程发送信号的权限pid -1    向进程组id等于pid的绝对值的所有进程发送信号int raise(int sig); 功能给调用进程自己发送信号 ​ void abort(void); 功能给调用进程自己发送信号SIGABRT(6)unsigned int alarm(unsigned int seconds); 功能让内核在seconds秒后向调用进程发送SIGALRM(14)信号 返回值上一次alarm剩余的时间如果是正常走完时间返回0如果时间还没走完又再次调用alarm后会覆盖之前的时间重新计时并不会产生多个闹钟信号 四、暂停和休眠 int pause(void); 功能让调用进程进入暂停态执行进入睡眠状态直到有信号终止进程或者有信号被捕获会唤醒并执行信号处理函数继续后面的执行流程。类似于不限时的sleep 返回值要么一直睡眠不返回睡醒返回-1 unsigned int sleep(unsigned int seconds); 功能让调用进程睡眠seconds秒除非有信号终止进程或者有信号被捕获也会唤醒 返回值剩余的睡眠秒数 ​ int usleep(useconds_t usec) 功能让调用进程睡眠usec微秒除非有信号终止进程或者有信号被捕获也会唤醒 返回值剩余的睡眠秒数 五、信号集与信号屏蔽 什么是信号集 是一种专门用于存储多个信号的数据类型 sigset_t 该类型占128字节每个字节代表了一种信号的有或无
操作信号集的相关函数 int sigemptyset(sigset_t *set); 功能将信号集set中的所有信号置零 清空信号集 ​ int sigfillset(sigset_t *set); 功能把信号集set中所有信号置1 ​ int sigaddset(sigset_t *set, int signum); 功能将信号集set中的信号signum置1 ​ int sigdelset(sigset_t *set, int signum); 功能将信号集set中的信号signum置0 ​ int sigismember(const sigset_t set, int signum); 功能测试信号集中是否存在signum信号 返回值存在返回1 不存在返回0 非法信号返回-1 #include stdio.h #include signal.h ​ int main(int argc,const char argv[]) {sigset_t set;sigfillset(set);sigemptyset(set); ​sigaddset(set,2);sigaddset(set,7); ​for(int i1; i128; i)                                               {   printf(信号%d 状态:%d\n,i,sigismember(set,i));}   } ​ 信号的递送与未决 当信号产生后系统内核会在其内部维护的进程表中给响应信号的进程设置一个对应的标志位着整个过程称为信号的递送 在信号产生到完成递送之间会存在一段时间间隔处于这个时间间隔的信号状态是“未决”
信号屏蔽 每个进程都有用一个信号掩码signal mask就是一个信号集其中存在的信号是需要被该进程屏蔽的信号 让需要屏蔽的信号处于“未决状态”当可以接收信号时让其退出未决状态完成递送 当执行一些特殊的且不想被干扰中断的操作时例如更新数据库敏感操作此时可以把信号放入信号屏蔽集中等操作完成后再从信号屏蔽集中删除继续处理信号能保证敏感操作的安全性
// 信号屏蔽集的操作函数 int sigprocmask(int how, const sigset_t *set, sigset_t oldset); 功能修改当前进程的信号掩码(屏蔽集) how修改信号掩码的方式SIG_BLOCK 将set中的信号加入到信号掩码中SIG_UNBLOCK 从信号掩码中把set中的信号删除SIG_SETMASK 把set中的信号替换掉信号掩码的所有信号 set信号集 用于设置 oldsel信号集 用于获取旧信号集 NULL则不获取 #include stdio.h     #include signal.h #include unistd.h ​ void sigint(int num) {   printf(按下了CtrlC\n); } void sigrtmin(int num) {printf(我可靠\n); } ​ int main(int argc,const char argv[]) {signal(SIGINT,sigint);signal(34,sigrtmin); ​sigset_t set,old_set;sigemptyset(set); ​// 给信号集添加信号sigaddset(set,SIGINT);sigaddset(set,34);// 设置信号屏蔽sigprocmask(SIG_BLOCK,set,old_set);printf(我是进程%u\n,getpid());sleep(15);printf(我醒了解除屏蔽!\n);// 还原屏蔽解除屏蔽sigprocmask(SIG_SETMASK,old_set,NULL);for(;;); } ​ 对于可靠和不可靠信号屏蔽的区别 对于不可靠信号通过信号屏蔽该信号后在信号屏蔽期间该信号产生多次都只会被屏蔽第一个只有第一个处于未决剩余的都不参与排队直接忽略当解除屏蔽后只会有第一个不可靠信号被完成递送 相反对于所有在屏蔽期间产生的可靠信号都会排队变成未决当屏蔽接触后会按照次序全部完成递送
六、带参的信号发送与捕获 可以让不同进程之间发送信号时带上一些简易数据完成不同进程之间简单通信这叫带参数的信号发送
#include signal.h ​ int sigaction (int signum, const struct sigaction* act,struct sigaction* oldact); 功能设置信号的处理方案 signum信号码 act信号处理方式 oldact原信号处理方式,可为NULL ​ struct sigaction {void (*sa_handler)(int); // 信号处理函数指针1void (sa_sigaction)(int,siginfo_t,void*); // 信号处理函数指针2 带附加数据sigset_t sa_mask; // 信号掩码//在信号函数函数执行过程中默认屏蔽当前信号如果想屏蔽其它信号可以向sa_mask中添加int sa_flags; // 信号处理标志void (sa_restorer)(void); // 保留NULL }; ​ sa_flags可为以下值的位或SA_ONESHOT/SA_RESETHAND 执行完一次信号处理后即对此信号的处理恢复为默认这也是老版本signal函数的缺省行为。SA_NODEFER/SA_NOMASK 在信号处理函数的执行过程中不屏蔽这个正在被处理的信号。SA_NOCLDSTOP 若signum参数取SIGCHLD则当子进程暂停时不通知父进程。SA_RESTART 系统调用一旦被signum参数所表示的信号中断会自行重启。SA_SIGINFO 使用信号处理函数指针2通过该函数的第二个参数提供更多信息。 ​ typedef struct siginfo {pid_t si_pid;   // 发送信号的PIDsigval_t si_value; // 信号附加值(需要配合sigqueue函数)… }siginfo_t; ​ typedef union sigval {int sival_int; 整数void sival_ptr; 指针 }sigval_t; ​ int sigqueue (pid_t pid, int sig,const union sigval value); 功能向pid进程发送sig信号附加value值(整数或指针)。 在默认情况下在信号处理函数的执行过程中会自动屏蔽这个正在被处理的信号而对于其它信号则不会屏蔽通过sigaction::sa_mask成员可以人为指定。 在信号处理函数的执行过程中需要加入进程信号掩码中的信号并在信号处理函数执行完之后自动解除对这些信号的屏蔽。 // 进程A #include stdio.h #include unistd.h #include signal.h ​ void sigint1 (int signum) {printf (收到SIGINT信号睡眠中…\n);sleep (3);printf (睡醒了。\n); } ​ void sigint2 (int signum, siginfo_t* si, void* pv) {printf (收到发自%u进程的SIGINT信号\n, si - si_pid);printf(附加的数据是%d\n,si-si_value.sival_int);//printf(%s\n,si-si_value.sival_ptr); } ​ int main () {printf(我是进程%u\n,getpid());struct sigaction act {};act.sa_handler sigint1;act.sa_sigaction sigint2;act.sa_flags SA_SIGINFO; ​sigaction (SIGINT, act, NULL);for (;;) pause (); ​return 0; } // 进程B 给进程A发送附带数据的信号 #include sys/wait.h ​ int main (void) {pid_t pid;printf(请输入进程号);scanf(%u,pid); ​sigval_t sv; sv.sival_int 6666;// sv.sival_ptr hehehe; ​if (sigqueue (pid, SIGINT, sv) -1) {   perror (sigqueue);return -1; }   return 0; } 七、定时器 系统为每个进程维护三个定时器 真实计时器进程运行的实际时间 虚拟计时器进程运行在用户态所消耗的时间 实用计时器进程运行在用户态和内核态消耗的时间之和
实际真正的时间真实计时器 用户态时间 内核时间 睡眠时间 状态切换耗时 通过设置计时器的起始时间和重复间隔时间给进程设置定时事件例如定时保存、定时上传操作。 获取\设置定时器 #include sys/time.h ​ int getitimer(int which, struct itimerval *curr_value); 功能获取当前进程的某个定时器的定时方案 ​ int setitimer(int which, const struct itimerval *new_value,struct itimerval old_value); 功能设置当前进程的定时方案 ​ which指定哪个定时器取值ITIMER_REAL 真实计时器 SIGALRM(14)ITIMER_VIRTUAL 虚拟计时器 SIGVTALRM(26)ITIMER_PROF 实用计时器 SIGVTALRM(26) ​ struct itimerval {struct timeval it_interval; // 间隔时间定时器开启后每间隔这个时间就会再发出一次定时器信号一直重复struct timeval it_value;    // 开始时间从该时间开始发送第一个定时器信号 }; ​ // 时间结构体 struct timeval {time_t      tv_sec;        // 秒数suseconds_t tv_usec;       //     微秒不能超过1000000 }; ​ #include stdio.h #include signal.h #include sys/time.h ​ void sigalrm(int num) {printf(闹钟响了!\n); } ​ int main(int argc,const char argv[]) {signal(SIGALRM,sigalrm); ​// 准备定时方案struct itimerval timer {{1,500000},{5,500000}}; ​// 设置定时器setitimer(ITIMER_REAL,timer,NULL); ​for(;;); }