第九周学习笔记

@

1. 信号的初步认识

1.1 信号的特点

信号所携带的信息量少,操作简单

1.2 信号的状态

  1. 产生
    ①由键盘产生:例如Ctrl+c,Ctrl+
    ②命令:kill
    ③系统函数:kil
    ④软条件:定时器
    ⑤硬件:段错误,除0错误

由键盘和和硬件产生的信号统称为硬件方式,其余的为软件方式

  1. 未决状态
    处在该状态的信号没有被处理。
  2. 递达状态
    信号被处理。处理信号的方式如下:
  • 忽略
  • 捕捉
  • 执行了默认动作

信号是由内核发送的,优先级比较高。进程收到信号后,会暂停正在处理的事情,优先处理信号,处理完成之后继续原来的工作

1.3 处理方式

  1. 忽略信号,这是大多程序对信号的处理方式,但SIGKILL和SIGSTOP信号不能被忽略。这是为了最后能够有一种方式结束掉进程

  2. 捕捉信号,捕捉信号后可以做相应的一些处理

  3. 执行默认动作,大多数信号的默认动作为终止进程

1.4 查看信号

使用 kill -l 命令可以查看信号

2.信号集

2.1 信号集的相关概念

  1. 未决信号集:没有被当前进程处理的信号

  2. 阻塞信号集:将某个信号放到阻塞信号集,这个信号就不会被进程处理,阻塞解除之后,信号被处理。

信号产生后,处于未决状态,进程受到信号后信号会被放入未决信号集中。在未决信号集中的信号等待被处理,进程会判断阻塞信号集中信号对应的标志位是否为1,如果为1不处理该信号,如果为0处理该信号

image

  1. 自定义信号集:用户可以使用自定义信号集对信号集进行操作。
    相关处理函数如下:
  • 将set集合置空
int sigemptyset(sigset_t *set);
  • 将所有信号加入set集合
int sigfillset(sigset_t *set);
  • 将signo信号加入到set集合
int sigaddset(sigset_t, *set, int signo);
  • 从信号集中移除signo信号
int sigdelset(sigset_t *set, int signo);
  • 判断信号是否存在
int sigismember(const sigset_t *set, int signo);
  • 检测信号集是否为空
int sigisemptyset(const sigset_t *set);
  • 按逻辑与方式将两个信号集并
int sigandset(sigset_t *set, const sigset_t *left, const sigset_t *right);

*按逻辑或方式将两个信号集并

int sigorset(sigset_t *set, const sigset_t *left, const sigset_t *right);

sigprocmask函数

  • 屏蔽按到接触信号屏蔽,将自定义信号集设置给阻塞信号集
  • 函数原型:
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

image

3. 信号的捕捉

  1. signal函数
typedef void (*sighandler_t)(int);
sighandler_t signal(
int signum, //要捕捉的信号
sighandler_t handler //执行的动作
);

handler是一个函数指针,函数指向的类型为*sighandler_t,即它指向的函数有一个int型参数,返回类型为void

如果handler不是函数指针,就必须设置为SIG_IN(忽略该信号),SIG_DFL(执行默认动作)

  1. sigaction函数:可以读取和修改与指定信号相关联的处理动作。
int sigaction(
int signum, //捕捉的信号
construction struct sigaction *act, //信号的处理函数
struct sigaction *oldact //旧的信号处理函数被存储在这
);

/*sigaction结构体*/
struct sigaction {
void (*sa_handler)(int); //信号的处理方式
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //在信号处理函数执行过程中,临时屏蔽指定的信号,额外屏蔽
int sa_flags; //通常设置为0
void (*sa_restorer)(void); //不再使用
};

处理方式:

  1. 若act为非空,则根据act结构体中的信号处理方式处理信号
  2. 若oldatc为非空,则根据原来的信号处理函数处理信号,根据act中的设置处理动作
  3. handler 的设置与上述signal的相同,如果handler不是函数指针,就必须设置为SIG_IN(忽略该信号),SIG_DFL(执行默认动作)

内核实现信号的捕捉

  1. 用户注册一个信号处理函数sighandler。
  2. 正在运行的程序,遇到中断、异常或是系统调用时进入内核态。
  3. 内核在处理完异常返回主函数之前,会检查有无信号未处理。检查到有信号未处理,并按照用户自定义的函数处理,如果没有自定义函数,则按照默认动作处理。
  4. 若设置了自定义处理函数,内核返回用户态执行sighandler函数
  5. 执行完sighandler函数后,执行系统调用sigreturn回到内核态
  6. 检查是否还有信号需要处理,如果没有就返回主程序继续主程序

chatgpt问答

image
image
image
image
image
image
image
image

posted @ 2023-11-11 18:45  20211212廖敏烨  阅读(16)  评论(0)    收藏  举报