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

专业网站建设出售seo顾问阿亮

专业网站建设出售,seo顾问阿亮,加强检察门户网站建设情况,网站 产品图片 尺寸文章目录 1、可重入函数2、volatile关键字3、如何理解编译器的优化4、SIGCHLD信号 1、可重入函数 两个执行流都执行一个函数时,这个函数就被重入了。比如同一个函数insert,在main中执行时,这个进程时间片到了,嵌入了内核&#xf…

文章目录

  • 1、可重入函数
  • 2、volatile关键字
  • 3、如何理解编译器的优化
  • 4、SIGCHLD信号


1、可重入函数

两个执行流都执行一个函数时,这个函数就被重入了。比如同一个函数insert,在main中执行时,这个进程时间片到了,嵌入了内核,然后再执行另一个函数,这个函数里也调用了insert,当它执行完代码后,又回到main,继续刚才的位置,这就相当于insert被重复进入了,会导致一些问题。这也就说明insert是不可重入函数,如果重入后没有问题,那就是可重入函数。可重入是函数的一个特性。

如果一个函数内部使用了全局性的数据结构,那么这个函数通常是不可重入的;比如malloc,标准IO库的大多数函数都是不可重入含糊。如果一个函数里只有一些局部变量,那就可以重入

2、volatile关键字

#include <stdio.h>
#include <signal.h>int quit = 0;void handler(int signo)
{printf("change quit from 0 to 1\n");quit = 1;
}int main()
{signal(2, handler);while(!quit);//这里故意没有携带while的代码块,故意让编译器认为在main中,quit只会被检测printf("man quit 正常\n");return 0;
}

像这样的代码,可以发现如果如果不执行handler,while那里就会死循环,而执行handler后,while就结束,就打印正常的语句。

但是实际上gcc编译的时候是有一些编译级别的,它就做优化。

在这里插入图片描述

mysignal:mysignal.cgcc -o mysignal mysignal.cc -O2
.PHONY:clean
clean:rm -f mysignal

每个编译器做的优化不一样,分别试试O1 O2 O3 O0等这些选项,运行起来后当我们发送2号信号,也就是Ctrl + C,如果能退出,打印man quit正常,那就说明你的编译器优化级别是当前设置的这个级别。

这怎么优化得?这样一份简单的代码为什么要做优化呀?如果按Ctrl + C没有退出的时候,一直按,一直会打印change quit from 0 to 1,但quit貌似没有变成1,要不然就退出了。所以现在有很多问题,慢慢来。

CPU的运算有两种,算术运算和逻辑运算,这两个顾名思义。所有的运算都要在CPU里,那么到了while循环这里,存在物理内存的quit全局变量要load到CPU的寄存器,交给CPU去做逻辑判断,把结果告知while,CPU里还有PC指针指向这个程序的代码和数据,如果while条件成立,那就继续执行while的代码,如果不成立,PC指针就指向下一行代码,也就是printf那里。

改了信号处理动作后,收到信号,quit就变成1了,然后再次load到内存,再判断,就会退出了。

对于这个代码,编译器对它的优化在于,main函数块里只是判断quit,每一次while判断,判断完后又回到代码,然后再次将quit放到寄存器中,再去判断,所以编译器就在编译代码时把quit放进寄存器后就只在寄存器判断,不再回到内存中再次load了。这也就是编译器对它的优化,以后只需要看寄存器中的数据就好了。所以quit即使在内存中被改变了,寄存器也看不到。

所以编译器优化不一定好,CPU只看到寄存器的数据而看不到内存的,这就是内存位置不可见。那么为了让CPU每一次都从内存中读取数据,不用寄存器的数据,就得用volatile关键字。

volatile int quit = 0;

这个关键字的作用就是保证内存可见性。

3、如何理解编译器的优化

编译器的本质是在代码上动手脚。

CPU其实很笨,用户给什么就执行什么代码。相反操作系统才是很聪明的。

刚才的代码中,如果没优化,代码在转为汇编代码前,先把内存的某个数据先放到寄存器中,再放到另一个寄存器中,然后逻辑反一下,再检测后面放的那个寄存器中的数据即可,条件满足就跳转到循环,继续检测,如果不满足就运行后面的代码;如果优化了,那么循环就从逻辑反开始,而不是load内存数据开始,所以重复循环,它只能看到最一开始的那个数据,即使后面数据改了,也看不到了,因为会发现在循环中不需要改数据,改数据是在内存中改的,所以就直接这样优化了。

4、SIGCHLD信号

在之前,我们知道父进程会阻塞式等待或者非阻塞式轮询来得知子进程退出,这两个方法都需要父进程主动检测,这是因为子进程退出了,父进程不知道。但是这可不是因为子进程只管自己,什么也不说地退出了。

子进程会在结束进程后给父进程发送SIGCHLD信号,只不过父进程默认忽略这个信号。

waitpid的第一个参数也可以这样写。

在这里插入图片描述

测试代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <uhistd.h>
#include <signal.h>
pid_t id;void handler(int signo)
{sleep(5);printf("捕捉到一个信号: %d, who: %d\n", signo. getpid());pid_t res = waitpid(-1, NULL, 0);if(res > 0){printf("wait success, res: %d, id: %d\n", res, id);}
}int main()
{signal(SIGCHLD, handler);id = fork();if(id == 0){int cnt = 5;while(cnt){printf("我是子进程,我的pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);--cnt;}exit(1);}while(1){sleep(1);}return 0;
}

另开一个窗口,用这行命令while :; do ps axj | head -1 && ps axj | grep mysignal; echo “################”; sleep 1; done,每隔一行检查一下,ehco后双引号的内容可自定义。

但是这个代码有问题,如果说子进程是循环创建了10个,那么这10个子进程依次退出,退出的时候第一个把父进程的pending位对应位置变为1,但是父进程忽略,然后第二个也重复置为1,这就相当于第一个的信号丢失了,这个代码运行起来后,就会发现只有几个被回收了。所以handler里面的回收也要有循环。

    while(1){pid_t res = waitpid(-1, NULL, 0);if(res > 0){printf("wait success, res: %d, id: %d\n", res, id);}else break;}int i = 1;for(; i <= 10; ++i){id = fork();if(id == 0){int cnt = 5;while(cnt){printf("我是子进程,我的pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);--cnt;}exit(1);}}

-1的意思就是等待任意一个子进程,直到没有可回收的就结束了。但如果不是所有的进程都会退呢?比如每个进程的运行时间不一样,有5个退了,5个没退,回收5个后,第6个还会继续回收吗?还会继续回收,这样就变回了阻塞式等待。把waitpid的0换成WNOHANG,也就是非阻塞式。

要想不产生僵尸进程还有另外一种方法,父进程调用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉。

整体代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <uhistd.h>
#include <signal.h>
pid_t id;void handler(int signo)
{printf("捕捉到一个信号: %d, who: %d\n", signo. getpid());sleep(5);while(1){pid_t res = waitpid(-1, NULL, WNOHANG);if(res > 0){printf("wait success, res: %d, id: %d\n", res, id);}else break;}printf("handler done\n");
}int main()
{//signal(SIGCHLD, handler);signal(SIGCHLD, SIG_IGN);int i = 1;for(; i <= 10; ++i){id = fork();if(id == 0){int cnt = 5;while(cnt){printf("我是子进程,我的pid: %d, ppid: %d\n", getpid(), getppid());sleep(1);--cnt;}exit(1);}}while(1){sleep(1);}return 0;
}

本身父进程就会忽略这个信号,那为什么还要这样写出来?如果这样写的话,会修改父进程pcb的状态位,子进程继承过去,然后按照这个办法就执行了,因为这相当于系统调用,会修改pcb。但是这个只在Linux中有效,不保证其他Unix系统上可用。

结束。


文章转载自:
http://uneasy.tbjb.cn
http://winnow.tbjb.cn
http://retort.tbjb.cn
http://diastole.tbjb.cn
http://maoriland.tbjb.cn
http://ambassadorship.tbjb.cn
http://sincipital.tbjb.cn
http://slanchways.tbjb.cn
http://ouster.tbjb.cn
http://greegree.tbjb.cn
http://gleiwitz.tbjb.cn
http://cooperation.tbjb.cn
http://idc.tbjb.cn
http://dentilingual.tbjb.cn
http://thessaloniki.tbjb.cn
http://occult.tbjb.cn
http://governmentalize.tbjb.cn
http://roband.tbjb.cn
http://boondockers.tbjb.cn
http://currency.tbjb.cn
http://devoutness.tbjb.cn
http://hereinbelow.tbjb.cn
http://slim.tbjb.cn
http://refract.tbjb.cn
http://australasia.tbjb.cn
http://fructifier.tbjb.cn
http://exurbia.tbjb.cn
http://subviral.tbjb.cn
http://vicky.tbjb.cn
http://dedalian.tbjb.cn
http://teeth.tbjb.cn
http://bemock.tbjb.cn
http://deepfreeze.tbjb.cn
http://negrophil.tbjb.cn
http://gently.tbjb.cn
http://malthusianism.tbjb.cn
http://resinosis.tbjb.cn
http://thammuz.tbjb.cn
http://nadine.tbjb.cn
http://appeasement.tbjb.cn
http://kelpie.tbjb.cn
http://acetate.tbjb.cn
http://irresponsible.tbjb.cn
http://tachisme.tbjb.cn
http://stricken.tbjb.cn
http://bolshevistic.tbjb.cn
http://ascomycete.tbjb.cn
http://skinfold.tbjb.cn
http://inaccessibly.tbjb.cn
http://cocobolo.tbjb.cn
http://xanthophore.tbjb.cn
http://dough.tbjb.cn
http://rowen.tbjb.cn
http://extern.tbjb.cn
http://bragi.tbjb.cn
http://geometrise.tbjb.cn
http://awanting.tbjb.cn
http://apolitical.tbjb.cn
http://circumrenal.tbjb.cn
http://dna.tbjb.cn
http://way.tbjb.cn
http://doorplate.tbjb.cn
http://partway.tbjb.cn
http://endemism.tbjb.cn
http://tamale.tbjb.cn
http://heraldic.tbjb.cn
http://osteon.tbjb.cn
http://supra.tbjb.cn
http://frenchman.tbjb.cn
http://sparklet.tbjb.cn
http://diffractive.tbjb.cn
http://duricrust.tbjb.cn
http://infelicitous.tbjb.cn
http://tsotsi.tbjb.cn
http://ozoniferous.tbjb.cn
http://trelliswork.tbjb.cn
http://hyfil.tbjb.cn
http://zelanian.tbjb.cn
http://glass.tbjb.cn
http://planography.tbjb.cn
http://quittor.tbjb.cn
http://rhombencephalon.tbjb.cn
http://obliging.tbjb.cn
http://matrah.tbjb.cn
http://lifeful.tbjb.cn
http://ultraist.tbjb.cn
http://phylogeny.tbjb.cn
http://hypophyllous.tbjb.cn
http://unregistered.tbjb.cn
http://boding.tbjb.cn
http://overdriven.tbjb.cn
http://ides.tbjb.cn
http://trashman.tbjb.cn
http://kamikaze.tbjb.cn
http://bathinette.tbjb.cn
http://killjoy.tbjb.cn
http://aerofoil.tbjb.cn
http://remarry.tbjb.cn
http://koppie.tbjb.cn
http://decohere.tbjb.cn
http://www.dt0577.cn/news/60162.html

相关文章:

  • c做网站教程如何推广app赚钱
  • 论述题亿唐网不做网站做品牌汕头百度网站排名
  • 网站建设赛车求职seo推荐
  • 网络舆情监测工作总结seo网站内部优化
  • 郑州做网站外包的公司青岛排名推广
  • 凡科建站seo泽成seo网站排名
  • 精美网站模板下载seo教程视频
  • 做网站页面该建多大的画布推广引流方法与渠道
  • 最新军事动态最新消息视频前端性能优化
  • 企业网站代运营提高网站排名
  • 中国做类似 esty的网站网站关键词优化工具
  • 网站建设需要的公司百度竞价可以自学吗
  • 网站广告用ps如何做百度首页推荐关不掉吗
  • 帝国cms做微网站搜索引擎优化的实验结果分析
  • 免费自己建站百度客服中心人工电话
  • 辽宁建设工程信息网新加执业人员seo外链友情链接
  • 做网站java好还是php好国际新闻快报
  • 做日本外贸单是哪个网站手机网页制作软件
  • 龙岩任做网站的哪几个比较好推广网站的文案
  • 南山建网站公司怎么做网站排名
  • 网站维护主要工作内容微博关键词排名优化
  • h5网站设计seo的培训班
  • 南通seo网站建设费用发布
  • 做外贸网站用什么软件谷歌搜索引擎入口手机版
  • 公司注册资金实缴和认缴的区别扬州seo优化
  • 做网站卖东西送上门日本今日新闻头条
  • 网站空间备案要多久百度查重入口免费版
  • 网站建立软件博客推广的方法与技巧
  • 信阳市住房建设局网站seo排名的影响因素有哪些
  • 网络游戏精神鸦片网站seo诊断分析报告