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

网站域名注册如何填写广告投放平台投放

网站域名注册如何填写,广告投放平台投放,网站 对比,wordpress刷评论目录 信号保存中重要的概念 内核中信号的保存 对sigset_t操作的函数 对block#xff0c;pendding#xff0c;handler三张表的操作 sigpromask ​编辑 sigpending 是否有sighandler函数呢#xff1f; 案例 信号处理 操作系统是如何运行的#xff1f; 硬件中断 …目录 信号保存中重要的概念 内核中信号的保存 对sigset_t操作的函数 对blockpenddinghandler三张表的操作 sigpromask ​编辑 sigpending 是否有sighandler函数呢 案例 信号处理 操作系统是如何运行的 硬件中断  时钟中断 软中断 死循环 缺⻚中断内存碎⽚处理除零野指针错误 理解用户态和内核态 信号的自定义捕捉  sigaction 验证阻塞信号 处理完解除对信号的阻塞 验证在处理前将pending表清零  验证sa_mask的作用 可重入函数 案例 volatile SIGCHLD信号 waitpid补充 验证子进程退出会给父进程发送SIGCHLD信号 基于信号对子进程回收 问题1 解决方法循环回收 问题2  信号保存中重要的概念 信号捕捉的三种方式1.默认 SIG_DFL  default 2.忽略  SIG_ING    ingore 3.自定义 信号递达实际执行信号的处理动作 信号未决信号从产生到递达的状态 信号阻塞进程可以阻塞某个信号  --阻塞/屏蔽特定信号信号产生了一定把信号pendding(保存并且信号永远不递达除非解除阻塞。 os信号的保存都与以上的三个概念有关 阻塞 vs 忽略 阻塞发生在为信号递达之前 忽略发生在信号递达 内核中信号的保存 内核数据结构示意图 pending:信号未决 block: 信号阻塞 handler:信号递达 进程维护了以上的结构所以进程是可以识别信号的。 以后对进程信号的操作都是为绕着这三张表展开的。 内核中的相应的数据结构 sigset_t 是信号集也是信号屏蔽字signal mask有blockpending 类似umask 对sigset_t操作的函数 对blockpenddinghandler三张表的操作 sigpromask 读取/修改进程屏蔽字 block表  set:进程中的block表修改基于set  oldset:修改前block表的模样 how以何种方式修改maskblock表 1. SIG_BLOCK:  mask mask | set  新增 2.SIG_UNBLOCK : mask mask ~set  去除指定信号 3.SIG_SETMASK: mask set  覆盖 sigpending 通过该函数可以知道pending表的情况 但为什么不设置一个输入型参数修改pending表呢 因为信号的产生都是在修改pending表 是否有sighandler函数呢 答案没有 那么如何修改handler表呢 signal就一直在修改啊 是否有恍然大悟的感觉啊。 案例 #include iostream #include unistd.h #include signal.h #include functional #include sys/types.h #include wait.h #include vector void PrintBlock(const sigset_t block) {std::coutblock[getpid()]: ;for (int i 31; i 0; i--){if (sigismember(block, i)){std::cout 1;}else{std::cout 0;}}std::cout std::endl; }void handler(int signo) {std::cout signo:signo 信号递达std::endl;exit(0); } int main() {signal(2,handler);sigset_t block, oldblock;sigemptyset(block);// 将二号新号加入sigaddset(block, 2);//阻塞二号信号int ret sigprocmask(SIG_SETMASK, block, oldblock);if (ret 0){perror(sigpromask);exit(1);}int cnt 0;while (true){PrintBlock(block);sleep(3);if(cnt5){PrintBlock(oldblock);//取消对二号信号的阻塞sigprocmask(SIG_SETMASK, oldblock, nullptr);}cnt;}return 0; }执行结果 一开始block表中二号信号被阻塞即使收到了二号信号也不能处理当修改block表二号没被阻塞时在执行二号信号相应的处理方法。 信号处理 信号没被处理被保存起来----合适的时候 那么什么是合适的时候 进程从用户态切换会用户态时检测额pending block决定是否用handler表处理信号。 os的运行状态 1.用户态 --- 执行用户写的代码 2.内核态  --执行内核代码 信号自定义捕捉的流程 操作系统是如何运行的 硬件中断  硬件中断的处理流程 中断向量表在os启动时就填充好了。 时钟中断 进程是由操作系统调度的那么操作系统谁有谁调度的呢 有个设备时钟源定期向cpu发送中断cpu处理中断执行中断处理历程而查表查到的终端服务是进程调度。 这样操作系统不就能自主调度了吗 时钟源是外设将中断传给cpu效率有点低现在的时钟源都是继承在cpu中。 主频就是控制CPU工作的时钟信号的频率 主频越快相应单位时间内操作系统执行的中断服务越多进程调度越频繁os的性能越高。 进程调度不一定切换进程 软中断 是否能不通过外设来产生中断呢 可以比如os支持系统调用cpu设计了汇编指令int 0x80 或 syscall,让cpu在内部触发中断逻辑 这样就可已在软件中触发中断--再根据中断号查系统调用表执行相应的系统调用 系统调用号的本质就是数组下标 死循环 无论是软中断还是硬件中断 os需要什么方法直接向中断向量表中添加就可以了os的本质就是一个死循环 void main(void) /* 这⾥确实是void并没错。 */ { /* 在startup 程序(head.s)中就是这样假设的。 */ ... /* * 注意!! 对于任何其它的任务pause()将意味着我们必须等待收到⼀个信号才会返 * 回就绪运⾏态但任务0task0是唯⼀的意外情况参⻅schedule()因为任 * 务0 在任何空闲时间⾥都会被激活当没有其它任务在运⾏时 * 因此对于任务0pause()仅意味着我们返回来查看是否有其它任务可以运⾏如果没 * 有的话我们就回到这⾥⼀直循环执⾏pause()。 */ for (;;) pause(); } // end main --------------------------------------------------------------------------------------------------------------------------------- 用户怎么把中断号给os寄存器如eax os怎么把返回值返回给用户 也是寄存器 用户和内核之间传递信息用的是寄存器。 系统调用--是通过软中断完成的 中断号--系统调用号写入寄存器eax--软中断--查表---执行相应的方法--将返回值写入寄存器返回给用户 既然执行系统调用需要触发软中断那我们使用系统调用函数值没有用 int 0x80 或 syscall 因为linux提供的系统调用接口不是C语言函数而是  系统调用号 约定的传递参数 用于内核和用户间传递信息的 系统调用号和返回值的寄存器  syscall  或 int 0x80 也就是说GNU glibc 把真正的系统调用封装---C语言封装版的系统调用 OS是躺在中断处理历程上的代码块。 缺⻚中断内存碎⽚处理除零野指针错误 这些错误都是通过软中断来处理的。 软中断有 1.陷阱  int 0x80 或 syscall 2.异常 CPU内部的软中断⽐如int 0x80或者syscall我们叫做 陷阱 • CPU内部的软中断⽐如除零/野指针等我们叫做 异常。所以能理解“缺⻚异常” 为什么这么叫了吗 理解用户态和内核态 内核页表整个系统只有一张 用户页表每个进程都有一张 对于任何进程不管如何调度任何进程都只能找到一个os 为什么只有一张内核页表 因为用户最关心的是系统调用。 用户关心系统调用的地址吗 不关心只需要知道系统调用号就可以了。 系统调用是在进程的地址空间中发起的但其执行是在内核地址空间中完成的。 1.调用任何函数库中都是在我们自己进程中的地址空间中进行的 操作系统无论怎么切换进程进程都只能找到一个操作系统 2.os调用方法的执行是在内核地址空间中执行的 不管是通过哪个进程的地址空间进入内核都是通过软中断进行操作的。 ⽤⼾态就是执⾏⽤⼾[0,3]GB时所处的状态 • 内核态就是执⾏内核[3,4]GB时所处的状态 如何区分内核态还是用户态 cpu中有cs段寄存器 用户如何进入内核态 1.时钟/外设中断 2.异常   cpu---软中断 3.陷阱    系统调用(int 0x80,syscall) 信号的自定义捕捉  1.前三步很好理解那么为什么要转为用户态来调用处理方法直接在内核态来处理不好吗 内核和用户的权限不同有安全风险并且用户来处理如果出了错误用户担责任。 2.信号处理完只能从内核返回因为处理函数的调用与main()函数之间不存在调用关心(栈区 3.如何继续执行原来的程序 cpu中有pc寄存器pc指针指向下一条要执行的命令只需要恢复pc指针的值就可以了。 sigaction 作用检查并修改handler表 sigaction结构  sa_handler :函数指针 sa_mask自定义屏蔽的信号  信号处理期间如果处理方法有系统调用那么就陷入内核态 os不允许信号处理方法嵌套---实现该方法的方式是将block表相应的信号置为1(阻塞该信号),但信号处理完会自动解除阻塞 什么时候pending表清0 在调用信号处理之前因为如果是处理完之后清零那么就无法区分pending中的1是处理进程时 收到的1还是处理完时的1                                                                                                                                                                                                                 验证阻塞信号 void PrintBlock() {sigset_t block;sigprocmask(SIG_SETMASK,nullptr,block);for(int i 31;i0;i--){if(sigismember(block,i))std::cout1;elsestd::cout0;}std::coutstd::endl; } void handler(int signo) {std::coutsigno: signostd::endl;while(true){PrintBlock();sleep(3);} }int main() {//signal(2,handler);struct sigaction act,oldact;act.sa_handler handler;sigaction(2,act,oldact);//std::cout执行std::endl;PrintBlock();while(true){pause();} }处理完解除对信号的阻塞 void PrintBlock() {sigset_t block;sigprocmask(SIG_SETMASK,nullptr,block);for(int i 31;i0;i--){if(sigismember(block,i))std::cout1;elsestd::cout0;}std::coutstd::endl; } void handler(int signo) {std::coutsigno: signostd::endl;// while(true)// {// PrintBlock();// sleep(3);// }PrintBlock();sleep(3); }int main() {//signal(2,handler);struct sigaction act,oldact;act.sa_handler handler;sigaction(2,act,oldact);//std::cout执行std::endl;PrintBlock();while(true){pause();PrintBlock();} } 验证在处理前将pending表清零  #include iostream #include unistd.h #include signal.h #include functional #include sys/types.h #include wait.h #include vector void PrintBlock() {sigset_t block;sigprocmask(SIG_SETMASK, nullptr, block);std::coutblock: ;for (int i 31; i 0; i--){if (sigismember(block, i))std::cout 1;elsestd::cout 0;}std::cout std::endl; } void PrintPending() {sigset_t pending;sigpending(pending);sigprocmask(SIG_SETMASK, nullptr, pending);std::coutpending: ;for (int i 31; i 0; i--){if (sigismember(pending, i))std::cout 1;elsestd::cout 0;}std::cout std::endl; } void handler(int signo) {std::cout signo: signo std::endl;// while(true)// {// PrintBlock();// sleep(3);// }PrintBlock();PrintPending();sleep(3); }int main() {// signal(2,handler);struct sigaction act, oldact;act.sa_handler handler;sigaction(2, act, oldact);// std::cout执行std::endl;PrintBlock();PrintPending();while (true){pause();PrintBlock();PrintPending();} }验证sa_mask的作用 void handler(int signo) {std::cout signo: signo std::endl;// while(true)// {// PrintBlock();// sleep(3);// }PrintBlock();//PrintPending();while(true){}//sleep(3); }int main() {// signal(2,handler);struct sigaction act, oldact;act.sa_handler handler;sigset_t mask;sigemptyset(mask);sigaddset(mask,2);sigaddset(mask,3);//把三号信号屏蔽act.sa_mask mask;//设置屏蔽信号sigaction(2, act, oldact);// std::cout执行std::endl;PrintBlock();//PrintPending();while (true){pause();//PrintBlock();//PrintPending();} } 屏蔽了2号和3号信号  可重入函数 一个函数被两个以上的执行流同时进入---重入(重复进入) 重入不出问题---可重入函数 重入出问题--- 不可重入函数---涉及对全局资源的处理 大部分库中的函数都是不可重入函数 重入和不可重入没有好坏之分只是特性。 案例 因为中断将node2插入链表head指向node2但返回main函数继续执行时head又指向了node1导致找不到node2,也就造成了内存泄漏。main和信号的处理是两个执行流进入的都是inset函数。 volatile volatile是易变关键字 #include stdio.h #include signal.h #include unistd.h int flag 1; void handler(int signo) {printf(signo:%d\n,signo);printf(flag - 0\n);flag 0;} int main() {signal(2,handler);while(flag);printf(quit normal!\n);return 0; } 没开启编译器优化会实时更新进程地址空间中flag的值 当把编译器的优化等级开高一些为什么不退出了呢 开了优化后即使进程内存地址空间中的flag改变了但cpu中的flag不会根据进程地址空间中的flag更新寄存器中的flag所以一直死循环没有退出 。 volatile flag 1;//加上volatile关键字 即使优化编译器优化等级开高了也实时通过进程地址空间中值修改寄存器中的值。  SIGCHLD信号 当子进程退回后----给父进程发送---SIGCHLD信号 waitpid补充 pid为-1时可以等待任何子进程。 验证子进程退出会给父进程发送SIGCHLD信号 #include iostream #include sys/types.h #include unistd.h #include signal.h #include wait.h void handler(int signo) {std::cout signo: signo std::endl;pid_t ret waitpid(-1, nullptr, 0);//pid-1,表示等待任何子进程if (ret 0){std::cout子进程: ret退出std::endl;}else if (ret 0){std::cout wait error std::endl;}sleep(3); } int main() {signal(SIGCHLD, handler);pid_t pid fork();if (pid 0){std::cout 我是子进程: ;std::cout getpid() std::endl;exit(0);}std::cout 我是父进程: getpid() std::endl;while (true);return 0; } 基于信号对子进程回收 问题1 如果有n个子进程同时给父进程发送SIGCHLD信号这是只能记录和处理一个信号 如果pending记录了一个信号其他的信号再发过来也不会被记录。 #include iostream #include sys/types.h #include unistd.h #include signal.h #include wait.h void handler(int signo) {std::cout signo: signo std::endl;pid_t ret waitpid(-1,nullptr,0);if(ret0){std::cout 子进程: ret 退出 std::endl;}else if(ret0){std::coutwait errorstd::endl;} } int main() {signal(SIGCHLD, handler);pid_t pid fork();for (int i 0; i 5; i){pid_t pid fork();if (pid 0){std::cout 我是子进程: ;std::cout getpid() std::endl;exit(0);}}while(true);return 0; } 创建了10个子进程只有7个子进程退出剩余的子进程发出的信号没有被处理这些子进程变为了僵尸 解决方法循环回收  void handler(int signo) {while (true){pid_t ret waitpid(-1, nullptr, 0);if (ret 0){std::cout 子进程: ret 退出 std::endl;// std::cout wait success std::endl;}else if (ret 0){std::cout 暂时回收完毕 std::endl;break;}} } 运行结果子进程全都被回收  没有僵尸子进程 问题2  基于问题1如果10个子进程中有几个进程迟迟不退出那么就会阻塞在信号处理那里等待子进程的退出 解决方法 options中有个WNOHANG如果没有子进程结束则立即返回0 这样处理方法就有阻塞变为了非阻塞如果有子进程退出则又会在进入循环回收一次往复避免了子进程出现僵尸。  pid_t ret waitpid(-1, nullptr, WNOHANG);
http://www.hkea.cn/news/14453610/

相关文章:

  • 网站备案流程以及所需资料wordpress您的密码重设链接无效
  • 自己做资讯网站海珠电子商务网站建设
  • wordpress增加边栏如何优化网络
  • 电子产品去什么网站做站点公司都是自己制作网站
  • 深圳住建设局网站公租房网站验收指标
  • 2019做网站图片用什么格式html国庆节网页制作代码
  • 深圳东莞网站开发石家庄最新新闻
  • 网站的设计与维护摘要宝安建网站公司
  • 网站可以做章子吗如何设计营销型网站建设
  • 十大素材网站宁波网站建设58同城
  • 档案安全网站安全建设男女直接做那个的视频网站
  • 专业的建设机械网站织梦网站怎么修改内容
  • 网站排版的优点静态摄影网站模板
  • 网站建设后续需要维护网站建设运营方案 团队
  • 国土资源局加强网站建设南昌网站设计哪个最好
  • 使用php如何做购物网站wordpress 副标题
  • 北京手机网站建设报价明年开春有望摘口罩
  • 怎么选择做网站的公司地图网站开发
  • 书籍网站设计wordpress 加描述 2017
  • 福州专业网站设计团队网站开发外包业务怎么接
  • 网站域名和网站网址吗潍坊做网站的那家好
  • 做糕点哪个网站网站链接维护怎么做
  • 松原企业网站建设公需科目在哪个网站做
  • 网站如何在360做提交椒江哪里可以做公司网站
  • 河南新蔡有做网站建设的吗那种软件可以做视频网站
  • 动效网站做cpa搭建哪个网站比较好
  • 网站教学视频侯马做网站
  • 网络推广外包网络优化网站建设
  • 买的网站模板怎么做沈阳网站建设蓝顶网络
  • 广州网站建设支付忻州网络公司网站建设