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

wordpress网站微信登录成都房地产协会

wordpress网站微信登录,成都房地产协会,个人网站建立,德阳网站建设 选哪家好朋友们、伙计们#xff0c;我们又见面了#xff0c;本期来给大家带来信号的保存和信号处理相关代码和知识点#xff0c;如果看完之后对你有一定的启发#xff0c;那么请留下你的三连#xff0c;祝大家心想事成#xff01; C 语 言 专 栏#xff1a;C语言#xff1a;从入… 朋友们、伙计们我们又见面了本期来给大家带来信号的保存和信号处理相关代码和知识点如果看完之后对你有一定的启发那么请留下你的三连祝大家心想事成 C 语 言 专 栏C语言从入门到精通 数据结构专栏数据结构 个  人  主  页 stackY、 C 专 栏   C Linux 专 栏  Linux ​  目录 1. 信号的保存 1.1 信号相关概念 1.2 信号的保存  1.3 处理位图的接口  2. 信号的处理  2.1 状态的切换 2.2 信号的处理 2.3 sigaction函数  3. 信号的其他补充  3.1 可重入函数 3.2 SIGCHLD信号  1. 信号的保存 1.1 信号相关概念 实际执行信号的处理动作称为信号递达(Delivery)。 信号递达的方式有三种 ① 信号的默认处理② 信号的忽略③ 信号的自定义捕捉 当我们自定义捕捉信号的时候使用的signal接口就是对指定信号进行捕捉然后去执行我们自定义的方法下面再来介绍一下两种用法 ① signal(signo, SIG_DFL)对指定信号恢复默认操作② signal(signo, SIG_IGN)对指定信号进行忽略忽略也算做对信号进行处理。 信号从产生到递达之间的状态称为信号未决(Pending)。进程可以选择阻塞 (Block )某个信号。被阻塞的信号产生时将保持在未决状态直到进程解除对此信号的阻塞才执行递达的动作。注意阻塞和忽略是不同的只要信号被阻塞就不会递达而忽略是在递达之后可选的一种处理动作。 1.2 信号的保存  当信号产生时我们不一定要立即对信号进行递达而是在合适的时候进行递达那么在信号未决时期我们要有能力将信号保存所以在进程PCB中会存在三张位图表用于保存信号 信号屏蔽字block表比特位的位置表示信号的编号、比特位的内容表示是否对特定信号进行屏蔽阻塞。 未决位图表pending表比特位的位置表示信号编号、比特位的内容表示特定的信号时候被递达。 handler表函数指针数组比特位的位置表示信号编号、比特位的内容是一个函数指针指向该信号的处理方法。 注意常规信号在递达之前产生多次只记一次 1.3 处理位图的接口  sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态,至于这个类型内部如何存储这些bit则依赖于系统实现,从使用者的角度是不必关心的使用者只能调用以下函数来操作sigset_ t变量 #include signal.h 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); 函数sigemptyset初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有效信号。函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系统支持的所有信号。注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号。函数sigaddset用于向指定的信号集添加某种信号。函数sigdelset用于删除指定信号集中的某种信号。函数sigismember用于判断指定信号在指定信号集是否存在。 对block表进行操作 #include signal.h int sigprocmask(int how, const sigset_t *set, sigset_t *oldset); 参数 ① set将要设置的新的信号屏蔽字 ② oldset获取旧的信号屏蔽字 ③ how修改block表的选项 SIG_BLOCKset包含了我们希望添加到当前信号屏蔽字的信号相当于mask mask l setSIG_UNBLOCK set包含了我们希望从当前信号屏蔽字中解除阻塞的信号相当于mask mask ~set SIG_SETMASK 设置当前信号屏蔽字为set所指向的值相当于  mask set 如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则 更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号 屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。   对pengding表操作 #include signal.h int sigpending(sigset_t *set); 参数 ① set获取当前进程的信号未决表 返回值 成功返回0出错返回-1 接下来通过这些接口我们可以实现一个动态的打印pending表的一个代码 #include iostream #include unistd.h #include signal.h #include sys/types.h using namespace std;// 打印pending表 void PrintPending(const sigset_t pending) {for (int signo 31; signo 0; signo--){if (sigismember(pending, signo)){std::cout 1;}else{std::cout 0;}}std::cout \n; }int main() {// 1. 屏蔽2号信号sigset_t set, oset;// 1.1 初始化信号集sigemptyset(set);sigemptyset(oset);// 1.2 添加信号sigaddset(set, 2);// 1.3 修改信号集sigprocmask(SIG_BLOCK, set, oset);// 2. 让进程不断获取当前进程的pendingint cnt 0;sigset_t pending;while (true){// 2.1 获取pending表sigpending(pending);// 2.2 打印PrintPending(pending);sleep(1);cnt;if (cnt 10){std::cout 解除对2号信号的屏蔽, 2号信号准备递达 std::endl;// 2.3 恢复原pending表sigprocmask(SIG_SETMASK, oset, nullptr);}}return 0; } 2. 信号的处理  2.1 状态的切换 进程会在合适的时候处理信号那么这个合适的时候是指什么时候呢 进程从内核态返回到用户态时进行信号的检测和处理。 用户态一种受控的状态能够访问的资源是有限的。内核态操作系统的工作状态能访问大部分的系统资源并且可以让用户以操作系统的身份访问内核空间。 ① 用户是无法直接访问OS底层资源只能通过系统调用间接访问所以用户调用系统调用必然包含了身份的变化② 进程要被调度首先得加载到内存然后通过页表映射到物理内存那么操作系统也是需要被映射到物理内存的③ 用户空间由用户级页表映射到物理内存④ 内核空间由内核级页表映射到物理内存所以在调用系统调用时访问OS直接在进程地址空间内进行跳转就如同函数调用一样调用系统调用接口也是在进程地址空间内进行的。 ① 操作系统的代码、系统调用、数据结构、数据在整个系统中只有一份所以内核级页表只需要有一张即可 ② 如果有多个进程只需将内核空间通过内核级页表映射到物理内存尽管有多个进程使用的也是同一份系统调用接口 ③ 无论进程如何调度CPU都可以直接找到操作系统 ④ 我们进程所有代码的执行都可以在自己的进程地址空间内通过跳转的方式进行调用和返回。 那么如何区分内核态和用户态呢 CPU内存在的寄存器CS寄存器CS寄存器用来保存代码段的其中有两个比特位01表示内核态1、11表示用户态3切换用户的状态其实就是修改CS寄存器中对应的比特位。 CPU内部还存在一些CR寄存器 CR3寄存器用于保存当前运行进程的用户级页表的物理地址 CR1寄存器用于保存上一次引发缺页中断的虚拟地址。 2.2 信号的处理 用户在调用系统调用之后在要完成调用任务时会从用户态切换至内核态完成对应的任务此时并不是直接切换回用户态而是先要检测信号如果有需要处理的信号根据对信号的处理方法如果是默认动作、忽略就直接处理如果是用户自定义方法那么此时不能在内核态处理而是要返回用户态去执行用户自定义方法在执行完之后不能直接跳转到用户代码处而是要再次返回内核态再从内核态返回进入内核态的用户代码处。 简化的图就是一个♾️ 在信号捕捉中一共会涉及到4次状态的切换 上述情况是只有一个信号需要被处理那么如果存在多个需要处理的信号那么在处理完一个信号之后会轮训式的检测需要处理的信号在所有信号处理完之后再切换为用户态。 2.3 sigaction函数  该函数是一个检测信号并改变处理动作的函数 参数 signum要改变的信号的编号 sigaction是一个结构体 其中我们只需要关注sa_handler和sa_mask sa_handler是要指定的处理动作 sa_mask是要额外屏蔽的信号集。 act表示要改变的新的处理方法 oldact表示被改变之前的处理方法。 Linux是不允许同一个信号已经在被处理的过程中再次进行嵌套处理的所以当某一个信号在被处理的过程中内核会自动将该信号加入到信号屏蔽字中当处理的函数返回之后会对该信号进行恢复除了当前处理的信号被屏蔽外我们也可以通过sa_mask信号集添加一些额外的信号进行屏蔽。  代码演示 #include iostream #include unistd.h #include signal.hvoid Print(const sigset_t pending);void handler(int signo) {std::cout get a sig: signo std::endl;sleep(1);while (true){sigset_t pending;sigpending(pending);Print(pending);sleep(1);} }// 打印pending表 void Print(const sigset_t pending) {for (int signo 31; signo 0; signo--){if (sigismember(pending, signo)){std::cout 1;}else{std::cout 0;}}std::cout std::endl; } int main() {std::cout pid: getpid() std::endl;struct sigaction act, oact;// 自定义处理方法act.sa_handler handler;// 初始化信号集sigemptyset(act.sa_mask);// 添加3号信号sigaddset(act.sa_mask, 3);// 自定义捕捉2号信号sigaction(2, act, oact);while (1)sleep(1);return 0; } 3. 信号的其他补充  3.1 可重入函数 将函数和信号结合起来研究 在链表阶段我们实现了一个头插的函数接口头插的阶段分为两步做完第一步的时候由于某些硬件中断使进程回到了内核态再次返回用户态时需要进行信号的检测与处理如果此时的信号自定义方法中也调用了头插的函数在做完头插的两步之后又重新返回用户态的代码处继续向下执行那么在自定义方法中插入的头节点就会被丢失掉此时这个头插的这个函数就是一个不可重入函数。 像上例这样insert函数被不同的控制流程调用有可能在第一次调用还没返回时就再次进入该函数,这称为重入insert函数访问一个全局链表有可能因为重入而造成错乱像这样的函数称为不可重入函数反之如果一个函数只访问自己的局部变量或参数,则称为可重入(Reentrant) 函数。 如果一个函数符合以下条件之一则是不可重入的 : 调用了malloc或free,因为malloc也是用全局链表来管理堆的。 调用了标准I/O库函数。标准I/O库的很多实现都以不可重入的方式使用全局数据结构。 3.2 SIGCHLD信号  在进程等待的章节说到过子进程退出时父进程必须进行等待waitpid()否则会造成僵尸问题并且我们有时还需要知道子进程的退出信息另外在子进程退出的时候回向父进程发送SIGCHLD信号。 #include iostream #include unistd.h #include signal.hvoid handler(int signo) {std::cout get a sig: signo std::endl; }int main() {std::cout pid: getpid() std::endl;// 自定义捕捉信号signal(SIGCHLD, handler);pid_t id fork();if (id 0){std::cout child is running std::endl;sleep(5);exit(10);}while (true)sleep(1);return 0; }父进程自定义捕捉SIGCHLD信号子进程在运行5秒后退出可以看到果然子进程给父进程发送了SIGCHLD信号。 所以我们就可以基于信号来对子进程进行回收等待了 #include iostream #include unistd.h #include signal.h #include sys/types.h #include sys/wait.hvoid handler(int signo) {std::cout get a sig: signo std::endl;// 等待任意进程waitpid(-1, nullptr, 0); }int main() {std::cout pid: getpid() std::endl;// 自定义捕捉信号signal(SIGCHLD, handler);pid_t id fork();if (id 0){std::cout child is running std::endl;sleep(5);exit(10);}while (true)sleep(1);return 0; } Linux支持手动忽略SIGCHLD如果对其进行忽略那么所有的子进程都不要父进程进行等待了子进程会在终止时自动的清理。 #include iostream #include unistd.h #include signal.hint main() {std::cout pid: getpid() std::endl;// 手动忽略SIGCHLDsignal(SIGCHLD, SIG_IGN);pid_t id fork();if (id 0){std::cout child is running std::endl;sleep(5);exit(10);}return 0; }朋友们、伙计们美好的时光总是短暂的我们本期的的分享就到此结束欲知后事如何请听下回分解~最后看完别忘了留下你们弥足珍贵的三连喔感谢大家的支持
http://www.dnsts.com.cn/news/140765.html

相关文章:

  • 拼多多网站建设框架图怎么做贝店式的网站
  • 电子商务网站设计的书优化大师怎么下载
  • 如何做医美机构网站观察分析塑料袋销售做哪个网站推广好
  • 蒙阴县城乡建设局网站网页模板dw
  • 网站seo优化是什么意思做公众号主页面的有哪些网站
  • 免费网站网络推广做网站能挣钱么
  • 做名宿比较好的网站江西网站开发多少钱
  • 李建忠 电子商务网站建设与管理 ppt广东建筑人才网招聘信息网
  • 网站服务器如何做端口映射关于门户网站建设经费的报告
  • wordpress加载插件自动优化网站建设
  • 宁波住房和城乡建设网站麦包包的网站建设
  • 建设职业技术学院网站大型网站运维公司
  • 超链接到网站怎么做百度公司图片
  • 长沙百度网站建设学做网站 为了熊掌号
  • 买购网官方网站手机如何制作代码
  • 智能科技网站模板下载地址wordpress近义词搜索
  • 深圳网站建设运营公司给国外做网站
  • 什么是商城网站建设专业微信网站建设公司首选公司
  • 怎么进网站源码的后台局域网内部网站建设app下载
  • 网站做搜索引擎优化wordpress深度优化
  • wordpress 导航站 模板wordpress群晖插件
  • 手机资讯网站源码成都商铺装修设计公司
  • 南宁专业做网站方案网页设计工程师工资多少
  • wordpress 纪念爱情网站搜索优化价格
  • 不用网站做淘宝客沈阳男科医院在哪
  • 代做安装预算的网站渭南做网站电话
  • 营销网站文章去那找如何用ps做照片模板下载网站
  • 个人网站设计作业dede网站源码 如何修改
  • 创建视频网站免费注册wordpress 论坛app
  • 一般用网站服务器网站建设+荆州