您的位置:首页 > 房产 > 建筑 > 合肥网站制作建设_河北建设工程信息网下载时间_软文营销成功案例_seo搜索优化公司

合肥网站制作建设_河北建设工程信息网下载时间_软文营销成功案例_seo搜索优化公司

2025/1/10 18:15:52 来源:https://blog.csdn.net/weixin_69032308/article/details/143693678  浏览:    关键词:合肥网站制作建设_河北建设工程信息网下载时间_软文营销成功案例_seo搜索优化公司
合肥网站制作建设_河北建设工程信息网下载时间_软文营销成功案例_seo搜索优化公司

1. 什么是进程?

从内核的角度,进程是系统分配资源的单位。当一个程序(静态)被加载到内存,操作系统为程序分配一个PCB(进程控制块)。

PCB:Process Control Block。在Linux中PCB叫做task_struct的结构体,我们称之为“进程描述符”。它里面包含了进程执行的所有信息,所以操作系统CPU对task_struct进行管理,相当于对进程进程管理。每一个进程都有一个PCB。


2. 信号的内核表示与信号阻塞

  • 信号递达:实际执行信号的处理动作。
  • 信号未决:信号从产生到递达之间的状态
  • 进程可以选择阻塞某个信号,被阻塞的信号产生时将保持在未决状态,直接进行解除对信号的阻塞,才会执行递达的动作
  • 阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达时可选的一种处理动作

3. 信号在内核中的表示

系统中的信号是发送给进程的,对于进程而言,信号是给进程的PCB(task_struct)发的,PCB使用位图结构(block位图、pending位图)结构记录收到的信号,这样进程执行时就知道自己收到什么信号了。

信号为什么要被保存在进程里?因为进程收到信号后,可能不会立即处理。这个信号从产生到递达之间的时间窗口内,进程需要记录该信号已经产生了,等到处理的时候才能知道哪些信号已经发生了。

  • 比特位的内容为1或0,表示是否收到某个信号
  • 比特位的位置(第几个),表示信号的编号c
  • 所谓的“发信号”,本质就是操作系统区修改tack_struct的信号位图的对应比特位,发送信号实际上就是写信号。

使用kill -l查看操作系统有哪些信号

kill -l

操作系统是进程的管理者,只有它才有资格去修改task_struct内部的属性,即操作系统需要提供相应的系统调用以实现信号的发送、阻塞等功能

task_struct中针对信号,包含了两张位图和一张函数指针表。分别是block位图pending位图handler处理函数指针表

  • block位图记录某个信号是否被阻塞,如果某个信号对应的比特为1表示该信号被阻塞,为0表示没有阻塞;对于被阻塞的信号,即使该信号产生了,进程也不会对该信号做任何处理。
  • pending位图记表示收到了哪些信号。如果收到某个信号,则会将对应的比特位置1;处理完某个信号后,会将对应的比特位置0。由于每个比特位只能表示信号的有无,若在信号产生到信号递达的时间窗口内,重复收到多个同样的信号,最终也只会递达一次。
  • handler函数指针数组用于记录对各个信号的处理方式。如果设置为SIG_DFL表示执行系统默认处理函数,设置为SIG_IGN表示忽略该信号;设置为用户空间的某个函数时,待信号递达时,则会从内核态切换回用户态以执行该部分代码

4. Linux常规信号一览表

1) SIGHUP: 当用户退出shell时,由该shell启动的所有进程将收到这个信号,默认动作为终止进程

2) SIGINT:当用户按下了<Ctrl+C>组合键时,用户终端向正在运行中的由该终端启动的程序发出此信号。默认动

作为终止进程。

3) SIGQUIT:当用户按下<ctrl+\>组合键时产生该信号,用户终端向正在运行中的由该终端启动的程序发出些信

号。默认动作为终止进程。

4) SIGILL:CPU检测到某进程执行了非法指令。默认动作为终止进程并产生core文件

5) SIGTRAP:该信号由断点指令或其他 trap指令产生。默认动作为终止里程 并产生core文件。

6) SIGABRT: 调用abort函数时产生该信号。默认动作为终止进程并产生core文件。

7) SIGBUS:非法访问内存地址,包括内存对齐出错,默认动作为终止进程并产生core文件。

8) SIGFPE:在发生致命的运算错误时发出。不仅包括浮点运算错误,还包括溢出及除数为0等所有的算法错误。默认动作为终止进程并产生core文件。

9) SIGKILL:无条件终止进程。本信号不能被忽略,处理和阻塞。默认动作为终止进程。它向系统管理员提供了可以杀死任何进程的方法。

10) SIGUSE1:用户定义 的信号。即程序员可以在程序中定义并使用该信号。默认动作为终止进程。

11) SIGSEGV:指示进程进行了无效内存访问。默认动作为终止进程并产生core文件。

12) SIGUSR2:另外一个用户自定义信号,程序员可以在程序中定义并使用该信号。默认动作为终止进程。

13) SIGPIPE:Broken pipe向一个没有读端的管道写数据。默认动作为终止进程。

14) SIGALRM: 定时器超时,超时的时间 由系统调用alarm设置。默认动作为终止进程。

15) SIGTERM:程序结束信号,与SIGKILL不同的是,该信号可以被阻塞和终止。通常用来要示程序正常退出。执行shell命令Kill时,缺省产生这个信号。默认动作为终止进程。

16) SIGSTKFLT:Linux早期版本出现的信号,现仍保留向后兼容。默认动作为终止进程。

17) SIGCHLD:子进程状态发生变化时,父进程会收到这个信号。默认动作为忽略这个信号。

18) SIGCONT:如果进程已停止,则使其继续运行。默认动作为继续/忽略。

19) SIGSTOP:停止进程的执行。信号不能被忽略,处理和阻塞。默认动作为暂停进程。

20) SIGTSTP:停止终端交互进程的运行。按下<ctrl+z>组合键时发出这个信号。默认动作为暂停进程。

21) SIGTTIN:后台进程读终端控制台。默认动作为暂停进程。

22) SIGTTOU: 该信号类似于SIGTTIN,在后台进程要向终端输出数据时发生。默认动作为暂停进程。

23) SIGURG:套接字上有紧急数据时,向当前正在运行的进程发出些信号,报告有紧急数据到达。如网络带外数据到达,默认动作为忽略该信号。

24) SIGXCPU:进程执行时间超过了分配给该进程的CPU时间 ,系统产生该信号并发送给该进程。默认动作为终止进程。

25) SIGXFSZ:超过文件的最大长度设置。默认动作为终止进程。

26) SIGVTALRM:虚拟时钟超时时产生该信号。类似于SIGALRM,但是该信号只计算该进程占用CPU的使用时间。默认动作为终止进程。

27) SGIPROF:类似于SIGVTALRM,它不公包括该进程占用CPU时间还包括执行系统调用时间。默认动作为终止进程。

28) SIGWINCH:窗口变化大小时发出。默认动作为忽略该信号。

29) SIGIO:此信号向进程指示发出了一个异步IO事件。默认动作为忽略。

30) SIGPWR:关机。默认动作为终止进程。

31) SIGSYS:无效的系统调用。默认动作为终止进程并产生core文件。

34) SIGRTMIN ~ (64) SIGRTMAX:LINUX的实时信号,它们没有固定的含义(可以由用户自定义)。所有的实时信号的默认动作都为终止进程。

9) SIGKILL 和19) SIGSTOP信号,不允许忽略和捕捉,只能执行默认动作。甚至不能将其设置为阻塞。

5. 信号集操作函数

信号集操作函数
int sigemptyset(sigset_t *set)将传入的set位图的各个位清零
int sigfillset(sigset_t *set)将传入的set位图的各个位置设置为1
int sigaddset(sigset_t *set, int signum)将signum信号在set中对应的比特位置设置为1
int sigdelset(sigset_t *set, inst signum)将signum信号在set中对应的比特位置设置为0
sigismember(const sigset_t *set, int signum)查看signum对应的比特位在set中是否为1,为1则返回1,否则返回0

注意,在使用sigset_t类型的变量之前,一定要调用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后,可以调用sigaddset和sigdelset在该信号集中添加或删除某种信号。

上述接口只是对sigset_t这个位图结构做操作,并未对block和pending位图直接做操作,下面介绍关于这两个位图的系统调用函数:sigprocmask和sigpending

5.1 sigprocmask读取/修改进程的信号屏蔽字(阻塞信号集/blocking位图)

第一个参数:how

how可以取值SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK.

  • SIG_BLOCK: set包含我们希望添加到当前信号屏蔽字中的信号,相当于mask=mask|set
  • SIG_UNBLOCK: set包含我们希望从当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set
  • SIG_SETMASK: 设置当前信号屏蔽字中解除阻塞的信号,相当于mask=mask&~set

第二个参数:set

用户自己定义的sigset_t类型的set

第三个参数:oldset

oldset是传出参数,调用sigprocmask系统调用函数之后,会传出调用该函数之前的进程的mask位图。

5.2 获取当前进程的信号屏蔽字

#include <stdio.h>
#include <signal.h>int main(){sigset_t oldset;sigprocmask(SIG_BLOCK,NULL,&oldset);for (int i = 1; i < NSIG; i++){if(sigismember(&oldset,i))printf("1");elseprintf("0");}printf("\n");return 0;
}

 注意:NSIG的取值是最大的信号数+1

5.3 信号集操作函数练习

#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
void sys_err(const char *str){perror(str);exit(1);
}void print_set(sigset_t *set){int i;for (i = 1; i < 32; i++){if (sigismember(set,i))putchar('1');elseputchar('0');}printf("\n");
}int main(){sigset_t set, oldset, pedset;int ret = 0;sigemptyset(&set);sigaddset(&set,SIGINT);ret = sigprocmask(SIG_BLOCK,&set,&oldset);if (ret == -1)sys_err("sigprocmask error");while(1){ret = sigpending(&pedset);if (ret == -1)sys_err("sigpending error");print_set(&pedset);sleep(1);}}

6. signal实现信号捕捉

注册一个信号捕捉函数。

该函数由ANSI定义,由于历史原因在不同版本的Unix和不同版本的Linux中可能有不同的行为。因此应该尽量避免使用它,取而代之使用sigaction函数。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void sig_catch(int signo){printf("catch you!!%d\n",signo);return;
}int main(){signal(SIGINT,sig_catch);while(1);return 0;}

7. sigaction实现信号捕捉

  注意sigaction的信号屏蔽字sa_mask,其作用域只存在于信号捕捉函数执行期间生效

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void sig_catch(int signo){printf("catch you!!%d\n",signo);return;
}int main(){struct sigaction act, oldact;act.sa_handler = sig_catch;sigemptyset(&(act.sa_mask));act.sa_flags = 0;int ret = sigaction(SIGINT,&act,&oldact);while(1);return 0;}

8. 信号捕捉的特性

  • 进程正常运行时,默认PCB中有一个信号屏蔽字,假定为△,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由△来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为△。
  • XXX信号捕捉函数执行期间,XXX信号自动被屏蔽(sa_flags = 0)
  • 阻塞的常规信号不支持排队,产生多次只记录一次。

9. 内核实现信号捕捉间析

10. 借助信号捕捉回收子进程

SIGCHILD的产生条件:

  • 子进程终止时
  • 子进程接收到SIGSTOP信号停止时
  • 子进程处在停止位置,接收到SIGCONT后唤醒时

借助SIGCHILD信号回收子进程:

子进程结束运行,其父进程会收到SIGCHILD信号。该信号的默认处理动作是忽略。可以捕捉该信号,在捕捉函数中完成子进程状态的回收。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com