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

网站制作实验报告适合机械网站的wordpress主题模板

网站制作实验报告,适合机械网站的wordpress主题模板,杭州网站优化方案,wordpress远程访问你很自由 充满了无限可能 这是很棒的事 我衷心祈祷你可以相信自己 无悔地燃烧自己的人生 -- 东野圭吾 《解忧杂货店》 信号的处理 1 信号的处理2 内核态 VS 用户态3 键盘输入数据的过程4 如何理解OS如何正常的运行5 如何进行信号捕捉信号处理的总结6 可重入函数volatile关… 你很自由 充满了无限可能 这是很棒的事 我衷心祈祷你可以相信自己 无悔地燃烧自己的人生 -- 东野圭吾 《解忧杂货店》 信号的处理 1 信号的处理2 内核态 VS 用户态3 键盘输入数据的过程4 如何理解OS如何正常的运行5 如何进行信号捕捉信号处理的总结6 可重入函数volatile关键字Thanks♪(ω)谢谢阅读下一篇文章见 1 信号的处理 处理信号本质就是递达这个信号首先我们来看如何进行捕捉信号信号的处理有三种 signal(2 , handler);//自定义 signal(2 , SIG_IGN);//忽略 signal(2 , SIG_DFL);//默认注意handler表是函数指针表传入的参数一定是函数指针类型 我们说过信号可能不会被立即处理而是在合适的时候进行处理。那么这个合适的时候到底是什么时候 进程从内核态处于操作系统的状态返回到用户态处在用户状态的时候进行处理 首先用户运行一个进程在执行代码指令时因为中断异常或者系统调用进如操作系统。进入操作操作系统就变为内核态操作系统处理完之后就对进程的三张表进行检查如果pending中存在继续判断如果被block了了就不进行处理反之执行对应方法执行对应的方法时如果是自定义方法会返回到用户层面的代码执行对应的方法。然后通过系统调用再次回到内核态。进入内核态之后再返回到原本的用户指令位置中 注意 操作系统不能直接转过去执行用户提供的handler方法因为操作系统权限太高了必须回到用户权限来执行方法类似一个∞符号 2 内核态 VS 用户态 再谈地址空间 这样无论进程如何切换,都可以找到OS!!! 所以我们访问OS,其实还是在我们的地址空间进行的和访问库函数没有区别OS不相信任何用户用户访问[3 , 4]地址空间要受到一定约束只能通过系统调用 3 键盘输入数据的过程 操作系统如何知道我们按下键盘呢肯定不能是每一时刻都进行检查这样消耗太大 在CPU中键盘按下时会向cpu发送硬件中断CPU就会读取中断号读到寄存器中CPU会告诉OS后续通过软件来读取寄存器。 内存中操作系统在启动时就会维护一张函数指针数组中断向量表数组下标是中断号数组内容是读磁盘函数读网卡函数等方法。每个硬件都有自己的中断号键盘也是。按下键盘时向CPU发送中断信号然后调用键盘读取方法将键盘数据读取到内存中这样就不需要轮询检查键盘是否输入了 4 如何理解OS如何正常的运行 根据我们使用电脑的经验电脑开机到关机的过程中本质一定是一个死循环。那这死循环是如何工作的呢那么CPU内部有一个时钟可以不断向CPU发送中断例如每隔10纳秒所以CPU可以被硬件推动下在死循环内部不断执行中断方法。来看Linux内核 在操作系统的主函数中首先是进行一些初始化包括系统调用方法然后就进入到了死循环 操作系统本质是一个死循环 时钟中断 不断调度系统任务 那么系统调用时什么东西呢 在操作系统内部操作系统提供给我们一张表系统调用函数表 平时我们用户层使用的fork , getpid , dup2...等都对应到底层的sys_fork , sys_getpid ...。只有我们找到特定数组下标系统调用号的方法就能执行系统调用了 回到之前的函数指针数组我们在这里再添加一个新方法用来调度任何的系统调用。使用系统调用就要有 系统调用号系统调用函数指针表操作系统内部 用户层面如何使用到操作系统中的函数指针表呢 这就要回到CPU中来谈CPU中两个寄存器假设叫做X 和 eax,当用户调用fork时函数内部有类似 mov 2 eax //将系统调用号放入寄存器中而所谓的中断不也是让CPU中的寄存器储存一个中断号来进行调用吗那CPU内部可不可以直接写出数字呢可以当eax获取到数字时寄存器X就会形成对应的数字来执行操作系统的系统调用。 通过这种方法就可以通过用户的代码跳转到内核来执行系统调用。但操作系统不是不相信任何用户吗怎么就直接跳转了呢用户是无法直接跳转到内存中的内核空间(3~4GB)。那么就有几个问题 操作系统如何阻止用户直接访问系统调用最终是可以被调用的又是如何做到的 在操作系统中解决这两种问题是非常复杂的有很多概念所以简单单来讲做到这些需要硬件CPU配合在CPU中存在一个寄存器code semgent记录代码段的起始与终止地址。就可以通过两个cs寄存器来分别储存用户与操作系统的代码CS寄存器中单独设置出两个比特位来记录是OS还是用户,这样就要区分了内核态和用户态。运行代码时就会检测当前权限与代码权限是否匹配进而做到阻止用户直接访问。而当我们调用系统调用中断异常时会改变状态变成内核态此时就可以调用系统调用 5 如何进行信号捕捉 今天我们来认识一个新的系统调用 NAMEsigaction, rt_sigaction - examine and change a signal actionSYNOPSIS#include signal.hint sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 使用方法和signal很像先介绍struct sigaction struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void); }; 在这其中我们只需要注意 void (*sa_handler)(int);,这是个函数指针就是自定义捕捉的函数方法。这样看来是不是就和signal很类似了 再来看看参数 int signum : 表示要对哪个信号进行捕捉const struct sigaction *act 输入型参数表示要执行的结构体方法struct sigaction *oldact 输出型参数获取更改前的数据 我们写一段代码来看看 // 创建一个进行进入死循环 // 对2号信号进行自定义捕捉void handler(int signum) {std::cout get a sig : signum pid: getpid() std::endl; }int main() {struct sigaction act, oact;// 自定义捕捉方法act.sa_handler handler;sigemptyset(act.sa_mask);act.sa_flags 0;sigaction(2, act, oact);while (true){std::cout I am a process... pid: getpid() std::endl;sleep(1);}return 0; } 我们运行看看 这样就成功捕捉了2号信号用起来和之前的signal很类似那么我们介绍这个干什么呢我们慢慢来说 首先信号处理有一个特性比如我们在处理二号信号的时候默认会对二号信号进行屏蔽对2号信号处理完成的时候会自动解除对2号信号的屏蔽也就是操作系统不允许对同一个信号进行递归式的处理 我们来简单验证一下:我们在handler方法中进行休眠看看传入下一个2号信号是否会进行处理 void handler(int signum) {std::cout get a sig : signum pid: getpid() std::endl;sleep(100); }来看 可见进程就屏蔽了对2号信号的处理 我们之前学习过三张表阻塞未决和抵达 既然操作系统对信号进行来屏蔽那么再次传入的信号应该就会被记录到未决表pending表中我们打印这个表来看看 void Print(sigset_t pending) {for (int sig 31; sig 0; sig--){if (sigismember(pending, sig)){std::cout 1;}else{std::cout 0;}}std::cout std::endl; }void handler(int signum) {std::cout get a sig : signum pid: getpid() std::endl;while (true){// 建立位图sigset_t pending;// 获取pendingsigpending(pending);Print(pending);} } 来看 可以看的我们在传入2号信号时就进入到了未决表中处理信号完毕就会解除屏蔽 接下来我们既可以来介绍sa_mask了上面只是对2号信息进行了屏蔽当我传入3号新号ctrl \时就正常退出了那么怎么可以在处理2号信号时屏蔽其他信号呢就是通过sa_mask,将想要屏蔽的信号设置到sa_mask中就会在处理2号信号的时候屏蔽所设置的信号 int main() {struct sigaction act, oact;// 自定义捕捉方法act.sa_handler handler;sigemptyset(act.sa_mask);//向sa_mask中添加3号信号sigaddset(act.sa_mask , 3);act.sa_flags 0;sigaction(2, act, oact);while (true){std::cout I am a process... pid: getpid() std::endl;sleep(1);}return 0; } 这样就也屏蔽了3号信号 当然如果把所有信号都屏蔽了肯定是不行的所以有一部分信号不能被屏蔽比如9号信号永远都不能屏蔽 信号处理的总结 对于信号我们学习了三个阶段 信号的产生与发送中断异常系统调用。信号的保存三张表阻塞未决和递达信号的处理 6 可重入函数 介绍一个新概念可重入函数。 我们先来看一个情景 这是一个链表我们的inser函数会进行一个头插头插会有两行代码 void insert(node_t* p) {p-next head;//------在这里接收到信号-----head p; }我们进行头插时进行完第一步之后突然来了一个信号但是我们之前说过信号处理时在用户态到内核态进行切换时才进行处理这链表的头插没有进行状态的切换啊其实状态的切换不一定只能是系统调用方法在时间片到了时钟中断之后也进行了状态的切换。 而且恰好该信号的自定义捕捉方法也是insert这时就导致node2插入到了链表中信号处理完之后头指针又被掰到node1了就造成node2丢失了内存泄漏了 这就叫做insert函数被重入了 在重入过程中一旦造成了问题就叫做不可重入函数因为一旦重入就造成了问题那当然不能重入了 绝大部分函数都是不可重入函数 volatile关键字 我们今天在信号的角度再来重温一下 volatile 作用保持内存的可见性告知编译器被该关键字修饰的变量不允许被优化对该变量的任何操作都必须在真实的内存中进行操作保持数据可见性 看这样一段代码 #include iostream #include signal.hint flag 0; void changdata(int signo) {std::cout get a sig : signo change flag 0-1 std::endl;flag 1; }int main() {signal(2 , changdata);while(!flag);std::cout process quit normal std::endl; } 主函数会一直进行死循环只有接收到了2号信号才会退出 但当我们进行编译优化时因为如果进程不接受到2号信号那么flag就没有人来修改编译器就认为没有任何代码对flag进行修改,共同有四级优化00 01 02 03 而while(!flag)是一个逻辑运算CPU 一般进行两种类别计算算术运算和逻辑运算会从内存进行读取然后进行运算 g main main.cc -01我们再次运行却发现进程不会结束了这是为什么因为优化直接将数据优化到寄存中因为编译器认为后续不会进行修改所以寄存器中的值不会改变程序只会读到寄存器中的值。所以就有了volatile关键字解决了这样的问题 Thanks♪(ω)谢谢阅读 下一篇文章见
http://www.w-s-a.com/news/75301/

相关文章:

  • php网站建设 关键技术做网站哪家正规
  • 网站开发用什么写得比较好谷歌的英文网站
  • 青岛网站建设公司在哪vivo手机商城
  • 兼职刷客在哪个网站做哪个网站做淘宝客
  • 眼科医院网站开发网络营销特点是什么
  • 提交网站给百度增加wordpress插件
  • 网站建设企业官网体验版是什么Wordpress哪个模板最快
  • 美丽说网站模板湖北可以做网站方案的公司
  • 北京西站进站最新规定建设网站的提成是多少
  • wordpress站点如何加速网站建设描述怎么写
  • 如何免费建造网站免费vi模板网站
  • 商丘做网站多少钱扬州大发网站建设
  • 网站建设哪家性价比高自己做项目的网站
  • 成立一个网站济宁营销型网站建设
  • 南通购物网站建设设计类平台网站
  • 专业网站建设咨询thinkphp网站源码下载
  • 怎么制作一个国外网站网站推广找哪家公司好
  • 免费做网站怎么做网站想在网上卖东西怎么注册
  • 淘宝网站建设的策划书网投怎么做网站
  • 如何免费做公司网站视频网站开发视频
  • 网站后台是怎么更新wordpress 大于2m的xm
  • 制作网页设计软件列表案例营销网站优化seo
  • 住房和建设建设局网站报告长官夫人在捉鬼
  • 用asp做网站需要什么软件天津建设工程信息网怎么注册
  • 一站式服务图片北京网站优化多少钱
  • 专业的论坛网站建设全网加速器
  • 成都品牌建设网站公司表单制作小程序
  • 手机端 网站 模板网页广告关不掉怎么办
  • 软装公司网站建设有没有做任务的网站
  • 加盟招商网站建设工业设计网站 知乎