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

做得比较好的公司网站做网站哪个便宜

做得比较好的公司网站,做网站哪个便宜,自动优化网站建设电话,在线解压rar网站本文目录 信号的概念1.1 core文件1.2 kill命令1.3 alarm函数1.4 setitimer调用1.5 signal捕捉信号1.6 信号集1.7 内核实现信号捕捉的过程1.8 sigaction1.9 sigchld 信号的概念 信号是 Linux 进程间通信的最古老的方式之一#xff0c;是事件发生时对进程的通知机制#xff0c… 本文目录 信号的概念1.1 core文件1.2 kill命令1.3 alarm函数1.4 setitimer调用1.5 signal捕捉信号1.6 信号集1.7 内核实现信号捕捉的过程1.8 sigaction1.9 sigchld 信号的概念 信号是 Linux 进程间通信的最古老的方式之一是事件发生时对进程的通知机制有时也称之为软件中断它是在软件层次上对中断机制的一种模拟是一种异步通信的方式。信号可以导致一个正在运行的进程被另一个正在运行的异步进程中断转而处理某一个突发事件。 发往进程的诸多信号通常都是源于内核。引发内核为进程产生信号的各类事件如下 对于前台进程用户可以通过输入特殊的终端字符来给它发送信号。比如输入CtrlC 通常会给进程 发送一个中断信号。硬件发生异常即硬件检测到一个错误条件并通知内核随即再由内核发送相应信号给相关进程。比如执行一条异常的机器语言指令诸如被 0 除或者引用了无法访问的内存区域。系统状态变化比如 alarm 定时器到期将引起 SIGALRM 信号进程执行的 CPU 时间超限或者该进程的某个子进程退出。运行 kill 命令或调用 kill 函数。 使用信号主要是两个目的一个是让进程知道已经发生了一个特定的事情强迫进程执行它自己代码中的信号处理程序。 信号的特点有简单、不能携带大量信息、满足某个特定条件才能发送、优先级比较高。 查看系统定义的信号列表kill -l前31个信号为常规信号其余为实时信号。 下面是所有进程对应的事件表。 信号的5种默认处理动作有Term终止进程、Ign当前进程忽略这个信号、Core终止进程 并且生成一个Core文件保存进程异常退出的错误信息、Stop暂停当前进程、Cont继续执行当前被暂停的进程。 信号的三种状态产生、未决、递达。其中比较特殊的是SIGKILL和SIGSTOP信号不能 被捕捉、阻塞或者忽略只能执行默认操作。 1.1 core文件 我们 创建一个简单的代码就是如下的代码。然后试着编译运行会发现会报错段错误核心已转储。 #include stdio.h #include string.hint main() {char * buf;//strcpy(buf, hello);return 0; }通过命令ulimit -a可以查看到对应的文件大小但是core file size这是0所以我们可以进行对应的修改。 通过命令ulimit -c 1024我们可以进行修改修改之后可以再进行对应的查看。 通过编译上面的代码为core.c然后运行会发现生成的core文件很大如下所示 通过命令gdb a.out进入到调试界面然后输入命令core-file core可以查看对应的core文件信息。 看到core中写着程序通过SIGSEGV访问了非法内存信号终止了后面也有对应的出错代码位置。 1.2 kill命令 #include sys/types.h #include signal.hint kill(pid_t pid, int sig);- 功能给任何的进程或者进程组pid, 发送任何的信号 sig- 参数- pid 0 : 将信号发送给指定的进程 0 : 将信号发送给当前的进程组 -1 : 将信号发送给每一个有权限接收这个信号的进程 -1 : 这个pid某个进程组的ID取反 -12345- sig : 需要发送的信号的编号或者是宏值(不同的系统编号可能会不一样)一般使用宏值0表示不发送任何信号kill(getppid(), 9);kill(getpid(), 9);int raise(int sig);- 功能给当前进程发送信号- 参数- sig : 要发送的信号- 返回值- 成功 0- 失败 非0kill(getpid(), sig); 这个命令等同于raise(9);void abort(void);- 功能 发送SIGABRT信号给当前的进程杀死当前进程kill(getpid(), SIGABRT);通过下面的demo可以模拟对应的kill命令的过程。 #include stdio.h #include sys/types.h #include signal.h #include unistd.hint main() {pid_t pid fork();if(pid 0) {// 子进程int i 0;for(i 0; i 5; i) {printf(child process\n);sleep(1);}} else if(pid 0) {// 父进程printf(parent process\n);sleep(2);printf(kill child process now\n);kill(pid, SIGINT);}return 0; } 1.3 alarm函数 #include unistd.h unsigned int alarm(unsigned int seconds);- 功能设置定时器闹钟。函数调用开始倒计时当倒计时为0的时候函数会给当前的进程发送一个信号SIGALARM- 参数seconds: 倒计时的时长单位秒。如果参数为0定时器无效不进行倒计时不发信号。取消一个定时器通过alarm(0)。- 返回值- 之前没有定时器返回0- 之前有定时器返回之前的定时器剩余的时间- SIGALARM 默认终止当前的进程每一个进程都有且只有唯一的一个定时器。alarm(10); - 返回0 第一次调用过了1秒alarm(5); - 返回9返回之前的定时器剩余时间alarm(100) - 该函数是不阻塞的#include stdio.h #include unistd.hint main() {int seconds alarm(5);printf(seconds %d\n, seconds); // 0sleep(2);seconds alarm(2); // 不阻塞printf(seconds %d\n, seconds); // 3while(1) { //设置while循环观察alarm2的效果}return 0; }定时器与进程的状态无关就算进程中有sleepalarm也会继续alarm采用的时自然定时法。 进程实际运行的时间 内核时间用户时间消耗的时间IO等 1.4 setitimer调用 首先struct itimerval是一个结构体用于定义定时器的参数。它的定义如下 struct itimerval {struct timeval it_interval; // 定时器的间隔时间struct timeval it_value; // 定时器的初始时间 };其中struct timeval的定义为也就是这个itimerval是多级嵌套的结构体 struct timeval {time_t tv_sec; // 秒suseconds_t tv_usec; // 微秒 };#include sys/time.h int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);- 功能设置定时器闹钟。可以替代alarm函数。精度微秒us可以实现周期性定时- 参数- which : 定时器以什么时间计时ITIMER_REAL: 真实时间时间到达发送 SIGALRM 常用ITIMER_VIRTUAL: 用户时间时间到达发送 SIGVTALRMITIMER_PROF: 以该进程在用户态和内核态下所消耗的时间来计算时间到达发送 SIGPROF- new_value: 设置定时器的属性struct itimerval { // 定时器的结构体struct timeval it_interval; // 每个阶段的时间间隔时间struct timeval it_value; // 延迟多长时间执行定时器};struct timeval { // 时间的结构体time_t tv_sec; // 秒数 suseconds_t tv_usec; // 微秒 };- old_value 记录上一次的定时的时间参数一般不使用指定NULL- 返回值成功 0失败 -1 并设置错误号#include sys/time.h #include stdio.h #include stdlib.h// 过3秒以后每隔2秒钟定时一次 int main() {struct itimerval new_value;// 设置间隔的时间new_value.it_interval.tv_sec 2;new_value.it_interval.tv_usec 0;// 设置延迟的时间,3秒之后开始第一次定时new_value.it_value.tv_sec 3;new_value.it_value.tv_usec 0;int ret setitimer(ITIMER_REAL, new_value, NULL); // 非阻塞的,执行完这个命令后下面的printf会立即执行。printf(定时器开始了...\n);if(ret -1) {perror(setitimer);exit(0);}return 0; }1.5 signal捕捉信号 #include signal.h typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler);- 功能设置某个信号的捕捉行为- 参数- signum: 要捕捉的信号- handler: 捕捉到信号要如何处理- SIG_IGN 忽略信号- SIG_DFL 使用信号默认的行为- 回调函数 : 这个函数是内核调用程序员只负责写捕捉到信号后如何去处理信号。回调函数- 需要程序员实现提前准备好的函数的类型根据实际需求看函数指针的定义- 不是程序员调用而是当信号产生由内核调用- 函数指针是实现回调的手段函数实现之后将函数名放到函数指针的位置就可以了。- 返回值成功返回上一次注册的信号处理函数的地址。第一次调用返回NULL失败返回SIG_ERR设置错误号比较特别的是 SIGKILL SIGSTOP不能被捕捉不能被忽略。 #include sys/time.h #include stdio.h #include stdlib.h #include signal.hvoid myalarm(int num) {printf(捕捉到了信号的编号是%d\n, num);printf(xxxxxxx\n); }// 过3秒以后每隔2秒钟定时一次 int main() {// 注册信号捕捉// signal(SIGALRM, SIG_IGN);// signal(SIGALRM, SIG_DFL);// void (*sighandler_t)(int); 函数指针int类型的参数表示捕捉到的信号的值。signal(SIGALRM, myalarm);struct itimerval new_value;// 设置间隔的时间new_value.it_interval.tv_sec 2;new_value.it_interval.tv_usec 0;// 设置延迟的时间,3秒之后开始第一次定时new_value.it_value.tv_sec 3;new_value.it_value.tv_usec 0;int ret setitimer(ITIMER_REAL, new_value, NULL); // 非阻塞的printf(定时器开始了...\n);if(ret -1) {perror(setitimer);exit(0);}getchar();return 0; }1.6 信号集 许多信号相关的系统调用都需要能表示一组不同的信号多个信号可使用一个称之为信号集的数据结构来表示其系统数据类型为 sigset_t。 在 PCB 中有两个非常重要的信号集。一个称之为“阻塞信号集”另一个称之为“未决信号集”。这两个信号集都是内核使用位图机制来实现的。但操作系统不允许我们直接对这两个信号集进行位操作。而需自定义另外一个集合借助信号集操作函数来对 PCB 中的这两个信号集进行修改。 信号的“未决”是一种状态指的是从信号的产生到信号被处理前的这一段时间。 信号的“阻塞”是一个开关动作指的是阻止信号被处理但不是阻止信号产生。 信号的阻塞就是让系统暂时保留信号留待以后发送。由于另外有办法让系统忽略信号所以一般情况下信号的阻塞只是暂时的只是为了防止信号打断敏感的操作。 进程的内核区有PCBPCB中有PID、PPID、文件描述符等同时也有未决信号集、阻塞信号集等这些东西。 来简述一下未决信号集和阻塞信号集的过程 第一段信号的产生与未决状态 用户通过键盘按下 Ctrl C会触发系统产生编号为2的信号 SIGINT。然而信号产生后并未立即被处理而是处于“未决”状态。在内核中所有未被处理的信号会被存储在一个特殊的集合中称为“未决信号集”。对于 SIGINT 信号其状态被记录在未决信号集的第二个标志位上。如果该标志位的值为 0则表示信号当前不是未决状态如果值为 1则表示信号处于未决状态等待被处理。 第二段信号处理与阻塞机制 在处理未决信号之前需要将其与另一个信号集——“阻塞信号集”进行比较。阻塞信号集默认情况下不阻塞任何信号但用户可以通过调用系统的API来设置某些信号的阻塞状态。在处理信号时系统会查询阻塞信号集中对应的标志位判断该信号是否被设置为阻塞。如果未被阻塞信号将被正常处理如果被阻塞则信号继续保持未决状态直到阻塞解除后信号才会被处理。 以下信号集相关的函数都是对自定义的信号集进行操作。int sigemptyset(sigset_t *set);- 功能清空信号集中的数据,将信号集中的所有的标志位置为0- 参数set,传出参数需要操作的信号集- 返回值成功返回0 失败返回-1int sigfillset(sigset_t *set);- 功能将信号集中的所有的标志位置为1- 参数set,传出参数需要操作的信号集- 返回值成功返回0 失败返回-1int sigaddset(sigset_t *set, int signum);- 功能设置信号集中的某一个信号对应的标志位为1表示阻塞这个信号- 参数- set传出参数需要操作的信号集- signum需要设置阻塞的那个信号- 返回值成功返回0 失败返回-1int sigdelset(sigset_t *set, int signum);- 功能设置信号集中的某一个信号对应的标志位为0表示不阻塞这个信号- 参数- set传出参数需要操作的信号集- signum需要设置不阻塞的那个信号- 返回值成功返回0 失败返回-1int sigismember(const sigset_t *set, int signum);- 功能判断某个信号是否阻塞- 参数- set需要操作的信号集- signum需要判断的那个信号- 返回值1 signum被阻塞0 signum不阻塞-1 失败#include signal.h #include stdio.h #include bits/types/sigset_t.hint main() {// 创建一个信号集sigset_t set;// 清空信号集的内容sigemptyset(set);// 判断 SIGINT 是否在信号集 set 里int ret sigismember(set, SIGINT);if(ret 0) {printf(SIGINT 不阻塞\n);} else if(ret 1) {printf(SIGINT 阻塞\n);}// 添加几个信号到信号集中sigaddset(set, SIGINT);sigaddset(set, SIGQUIT);// 判断SIGINT是否在信号集中ret sigismember(set, SIGINT);if(ret 0) {printf(SIGINT 不阻塞\n);} else if(ret 1) {printf(SIGINT 阻塞\n);}// 判断SIGQUIT是否在信号集中ret sigismember(set, SIGQUIT);if(ret 0) {printf(SIGQUIT 不阻塞\n);} else if(ret 1) {printf(SIGQUIT 阻塞\n);}// 从信号集中删除一个信号sigdelset(set, SIGQUIT);// 判断SIGQUIT是否在信号集中ret sigismember(set, SIGQUIT);if(ret 0) {printf(SIGQUIT 不阻塞\n);} else if(ret 1) {printf(SIGQUIT 阻塞\n);}return 0; }运行上面的代码可以看到下面的结果。 1.7 内核实现信号捕捉的过程 1.8 sigaction #include signal.h int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);- 功能检查或者改变信号的处理。信号捕捉- 参数- signum : 需要捕捉的信号的编号或者宏值信号的名称- act 捕捉到信号之后的处理动作- oldact : 上一次对信号捕捉相关的设置一般不使用传递NULL- 返回值成功 0失败 -1struct sigaction {// 函数指针指向的函数就是信号捕捉到之后的处理函数void (*sa_handler)(int);// 不常用void (*sa_sigaction)(int, siginfo_t *, void *);// 临时阻塞信号集在信号捕捉函数执行过程中临时阻塞某些信号。sigset_t sa_mask;// 使用哪一个信号处理对捕捉到的信号进行处理// 这个值可以是0表示使用sa_handler; 也可以是SA_SIGINFO表示使用sa_sigactionint sa_flags;// 被废弃掉了void (*sa_restorer)(void); };#include sys/time.h #include stdio.h #include stdlib.h #include signal.hvoid myalarm(int num) {printf(捕捉到了信号的编号是%d\n, num);printf(xxxxxxx\n); }// 过3秒以后每隔2秒钟定时一次 int main() {struct sigaction act;act.sa_flags 0;act.sa_handler myalarm;sigemptyset(act.sa_mask); // 清空临时阻塞信号集// 注册信号捕捉sigaction(SIGALRM, act, NULL);struct itimerval new_value;// 设置间隔的时间new_value.it_interval.tv_sec 2;new_value.it_interval.tv_usec 0;// 设置延迟的时间,3秒之后开始第一次定时new_value.it_value.tv_sec 3;new_value.it_value.tv_usec 0;int ret setitimer(ITIMER_REAL, new_value, NULL); // 非阻塞的printf(定时器开始了...\n);if(ret -1) {perror(setitimer);exit(0);}// getchar();while(1);return 0; }1.9 sigchld SIGCHLD信号在三种情况下会被发送给父进程当子进程结束、子进程暂停例如被信号暂停执行或子进程从暂停状态恢复运行时。然而默认情况下父进程会忽略SIGCHLD信号。通过正确处理SIGCHLD信号父进程可以在子进程结束时及时调用wait或waitpid函数来收集子进程的状态信息并清理其资源从而避免子进程变成僵尸进程。这种方法是解决僵尸进程问题的有效手段。 下面的demo是创建多个子进程并在父进程中处理子进程结束时产生的SIGCHLD信号。为了避免在信号处理函数注册完成之前子进程就已经结束并发送SIGCHLD信号代码首先将SIGCHLD信号阻塞直到信号处理函数注册完成后再解除阻塞。父进程会持续运行并打印其进程ID而子进程会在创建后立即退出。 首先初始化信号集并阻塞SIGCHLD信号使用sigset_t类型定义一个信号集set并通过sigemptyset将其初始化为空。 用sigaddset将SIGCHLD信号添加到信号集中。调用sigprocmask将SIGCHLD信号添加到当前进程的信号屏蔽集中从而阻塞SIGCHLD信号防止其在信号处理函数注册完成之前被处理。 使用fork函数创建多个子进程。在for循环中每次调用fork都会创建一个子进程。子进程在创建后立即退出而父进程会继续运行。子进程退出时会向父进程发送SIGCHLD信号但由于信号已经被阻塞因此不会立即触发信号处理函数。 在父进程中定义一个struct sigaction结构体act并设置其sa_handler为自定义的信号处理函数myFun。 使用sigemptyset清空act.sa_mask确保信号处理函数执行时不会被其他信号中断。 调用sigaction将SIGCHLD信号的处理函数设置为myFun。 调用sigprocmask将SIGCHLD信号从信号屏蔽集中移除解除阻塞允许信号被处理。 #include stdio.h #include unistd.h #include sys/types.h #include sys/stat.h #include signal.h #include sys/wait.h #include bits/types/sigset_t.h #include bits/sigaction.hvoid myFun(int num) {printf(捕捉到的信号 %d\n, num);// 回收子进程PCB的资源// while(1) {// wait(NULL); // }while(1) {int ret waitpid(-1, NULL, WNOHANG);if(ret 0) {printf(child die , pid %d\n, ret);} else if(ret 0) {// 说明还有子进程或者break;} else if(ret -1) {// 没有子进程break;}} }int main() {// 提前设置好阻塞信号集阻塞SIGCHLD因为有可能子进程很快结束父进程还没有注册完信号捕捉sigset_t set;sigemptyset(set);sigaddset(set, SIGCHLD);// 这是一个函数用于设置当前进程的信号屏蔽集。// 信号屏蔽集决定了哪些信号会被暂时阻塞即不会被立即处理。// SIG_BLOCK这是一个常量表示将信号集中的信号添加到当前进程的信号屏蔽集中即阻塞这些信号。sigprocmask(SIG_BLOCK, set, NULL);// 创建一些子进程pid_t pid;for(int i 0; i 20; i) {pid fork();if(pid 0) {break;}}if(pid 0) {// 父进程// 捕捉子进程死亡时发送的SIGCHLD信号struct sigaction act;act.sa_flags 0;act.sa_handler myFun;sigemptyset(act.sa_mask);sigaction(SIGCHLD, act, NULL);// 注册完信号捕捉以后解除阻塞 sigprocmask(SIG_UNBLOCK, set, NULL);while(1) {printf(parent process pid : %d\n, getpid());sleep(2);}} else if( pid 0) {// 子进程printf(child process pid : %d\n, getpid());}return 0; }
http://www.hkea.cn/news/14583922/

相关文章:

  • 网站建设风险评估个人网页模板免费下载
  • 网站域名解析页面太原网络广告公司
  • 企业网站建设成本qq刷网站空间
  • 网站的申请网站推广方案中评价效果是指
  • 大网站设计wordpress 如何去掉图片地址
  • 外链建设都需要带网站网址注册公司材料怎么准备
  • 做餐饮加盟的网站常州做半导体的公司
  • 社交网站做强自己做网站的步骤
  • 东莞网站建设用哪种好网站建设与管理插图
  • 上海网站建设收费小豹子韬韬是哪个网站做的
  • 永康电子商务网站建设公司网上怎么查公司信息
  • 怎么在网站空间上传文件p2p理财网站开发流程图
  • 做网站的html代码格式网页制作公司有哪些职位
  • 网站开发软件d网站网络推广
  • 网站免费推广平台php网站开发范例
  • 网站设计可以吗做一个网站花费多少钱
  • 有没有介绍做私家导游的网站东莞seo技术培训
  • 网站js聊天代码企业如何在工商网站上做公示
  • 郑州php网站开发培训wap网站是什么意思啊
  • 无锡市住房建设局网站wordpress新建页面子页面
  • 基于flash网站设计公司网站制作注意什么
  • 泉州做网站优化的公司燕郊网站制作
  • 如何获取网站开发语言广州免费旅游景点大全
  • 做网站在桂林网站seo
  • 海南建设大厅网站网站如何被谷歌收录
  • 许昌市建设投资有限公司 网站网站建设 点指成名
  • 请问下网站开发怎么弄wordpress博客内容预览
  • 北仑网站网页建设吴忠市建设局官方网站
  • 平山县建设局网站django做网站怎样
  • 营销型 展示类网站镇江百度网站排名