> For the complete documentation index, see [llms.txt](https://man.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://man.bsdcn.org/compat-43/sigvec.2.md).

# sigvec(2)

`sigvec` — 软件信号设施

## 名称

`sigvec`

## 库

Lb libc

## 概要

```c
#include <signal.h>
```

```c
struct sigvec {
	void     (*sv_handler)();
	int      sv_mask;
	int      sv_flags;
};
```

```c
int
sigvec(int sig, struct sigvec *vec, struct sigvec *ovec)
```

## 描述

**此接口由 sigaction(2) 取代。**

系统定义了一组可传递给进程的信号。信号传递类似于硬件中断的发生：信号被阻止再次发生，保存当前进程上下文，并构建新的上下文。进程可以指定一个*处理程序*来接收信号，或指定信号被*屏蔽*或*忽略*。进程还可以指定信号发生时系统采取的默认动作。通常，信号处理程序在进程的当前栈上执行。可以按每个处理程序更改此设置，使信号在特殊的*信号栈*上处理。

所有信号具有相同的*优先级*。信号例程执行时，导致其调用的信号被*屏蔽*，但其他信号仍可能发生。全局*信号掩码*定义了当前阻止传递给进程的信号集。进程的信号掩码从其父进程初始化（通常为 0）。可以通过 sigblock(2) 或 [sigsetmask(2)](/compat-43/sigsetmask.2.md) 调用更改，也可以在信号传递给进程时更改。

当进程出现信号条件时，该信号被添加到进程的待处理信号集中。如果该信号当前未被进程*屏蔽*，则将其传递给进程。信号传递时，保存进程的当前状态，计算新的信号掩码（如下所述），并调用信号处理程序。处理程序的调用方式使得如果信号处理例程正常返回，进程将在信号传递之前的上下文中恢复执行。如果进程希望在不同的上下文中恢复，则必须自行安排恢复先前的上下文。

当信号传递给进程时，在进程信号处理程序执行期间（或直到调用 sigblock(2) 或 [sigsetmask(2)](/compat-43/sigsetmask.2.md)）安装新的信号掩码。此掩码由当前信号掩码、添加要传递的信号、以及与要调用的处理程序关联的信号掩码进行*或*运算形成。

`sigvec` 函数为特定信号分配处理程序。如果 `vec` 非零，它指定传递指定信号时使用的处理程序例程和掩码。此外，如果 `sv_flags` 中设置了 `SV_ONSTACK` 位，系统将在由 sigaltstack(2) 指定的*信号栈*上向进程传递信号。如果 `ovec` 非零，信号之前的处理信息将返回给用户。

以下是所有信号的列表，名称与头文件 `<signal.h>` 中的定义一致：

| **名称**      | **默认动作** | **描述**                       |
| ----------- | -------- | ---------------------------- |
| `SIGHUP`    | 终止进程     | 终端线路挂起                       |
| `SIGINT`    | 终止进程     | 中断程序                         |
| `SIGQUIT`   | 创建核心映像   | 退出程序                         |
| `SIGILL`    | 创建核心映像   | 非法指令                         |
| `SIGTRAP`   | 创建核心映像   | 跟踪陷阱                         |
| `SIGABRT`   | 创建核心映像   | abort(3)（原为 `SIGIOT`）        |
| `SIGEMT`    | 创建核心映像   | 仿真指令执行                       |
| `SIGFPE`    | 创建核心映像   | 浮点异常                         |
| `SIGKILL`   | 终止进程     | 终止程序                         |
| `SIGBUS`    | 创建核心映像   | 总线错误                         |
| `SIGSEGV`   | 创建核心映像   | 段违规                          |
| `SIGSYS`    | 创建核心映像   | 调用不存在的系统调用                   |
| `SIGPIPE`   | 终止进程     | 向无读取者的管道写入                   |
| `SIGALRM`   | 终止进程     | 实时定时器超时                      |
| `SIGTERM`   | 终止进程     | 软件终止信号                       |
| `SIGURG`    | 丢弃信号     | 套接字上出现紧急条件                   |
| `SIGSTOP`   | 停止进程     | 停止（无法捕获或忽略）                  |
| `SIGTSTP`   | 停止进程     | 来自键盘的停止信号                    |
| `SIGCONT`   | 丢弃信号     | 停止后继续                        |
| `SIGCHLD`   | 丢弃信号     | 子进程状态改变                      |
| `SIGTTIN`   | 停止进程     | 后台尝试从控制终端读取                  |
| `SIGTTOU`   | 停止进程     | 后台尝试向控制终端写入                  |
| `SIGIO`     | 丢弃信号     | 可能在描述符上进行 I/O（参见 fcntl(2)）   |
| `SIGXCPU`   | 终止进程     | 超过 CPU 时间限制（参见 setrlimit(2)） |
| `SIGXFSZ`   | 终止进程     | 超过文件大小限制（参见 setrlimit(2)）    |
| `SIGVTALRM` | 终止进程     | 虚拟时间闹钟（参见 setitimer(2)）      |
| `SIGPROF`   | 终止进程     | 概要分析定时器闹钟（参见 setitimer(2)）   |
| `SIGWINCH`  | 丢弃信号     | 窗口大小改变                       |
| `SIGINFO`   | 丢弃信号     | 来自键盘的状态请求                    |
| `SIGUSR1`   | 终止进程     | 用户定义信号 1                     |
| `SIGUSR2`   | 终止进程     | 用户定义信号 2                     |

信号处理程序安装后，将保持安装状态，直到再次调用 `sigvec` 或执行 execve(2)。可以通过将 `sv_handler` 设置为 `SIG_DFL` 来重置特定信号的默认动作。默认动作包括：终止进程（可能伴随核心转储）、无动作、停止进程或继续进程。各信号的默认动作参见上方的信号列表。如果 `sv_handler` 为 `SIG_IGN`，信号的当前和待处理实例将被忽略并丢弃。

如果在以下列出的系统调用期间捕获到信号，调用通常会重启。通过在 `sv_flags` 中设置 `SV_INTERRUPT` 位，可以强制调用以 `EINTR` 错误提前终止。受影响的系统调用包括：在通信通道或慢速设备（如终端，但不包括普通文件）上的 read(2)、write(2)、sendto(2)、recvfrom(2)、sendmsg(2) 和 recvmsg(2)，以及 wait(2) 或 ioctl(2) 期间。但是，已经提交的调用不会重启，而是返回部分成功（例如，较短的读取计数）。

在 fork(2) 或 vfork(2) 之后，所有信号、信号掩码、信号栈以及重启/中断标志都由子进程继承。

execve(2) 系统调用恢复所有被捕获信号的默认动作，并将所有信号重置为在用户栈上捕获。被忽略的信号保持忽略状态；信号掩码保持不变；中断系统调用的信号继续如此。

## 注释

`vec` 中指定的掩码不允许屏蔽 `SIGKILL` 或 `SIGSTOP`。系统会静默处理此事。

`SV_INTERRUPT` 标志在 4.2BSD 中不可用，因此如果需要向后兼容则不应使用。

## 返回值

成功完成时，`sigvec` 函数返回值 0；否则返回值 -1，并设置全局变量 `errno` 以指示错误。

## 实例

在 VAX-11 上，处理程序例程可以声明为：

```c
void handler(sig, code, scp)
int sig, code;
struct sigcontext *scp;
```

其中 `sig` 是信号编号，硬件故障和陷阱按如下定义映射到信号编号。`code` 参数是下方给出的常量，或者对于兼容模式故障，是硬件提供的代码（兼容模式故障通过在 psl 中设置 `PSL_CM` 来与其他 `SIGILL` 陷阱区分）。`scp` 参数是指向 `sigcontext` 结构（定义在 `<signal.h>` 中）的指针，用于恢复信号之前的上下文。

## 错误

`sigvec` 函数将失败且不安装新的信号处理程序，如果发生以下情况之一：

**\[`EFAULT`]** `vec` 或 `ovec` 指向不属于进程地址空间有效部分的内存。

**\[`EINVAL`]** `sig` 参数不是有效的信号编号。

**\[`EINVAL`]** 试图忽略或为 `SIGKILL` 或 `SIGSTOP` 提供处理程序。

## 参见

[kill(1)](/man1/kill.1.md), kill(2), ptrace(2), sigaction(2), sigaltstack(2), sigblock(2), [sigpause(2)](/compat-43/sigpause.2.md), sigprocmask(2), [sigsetmask(2)](/compat-43/sigsetmask.2.md), sigsuspend(2), setjmp(3), siginterrupt(3), signal(3), sigsetops(3), [tty(4)](/man4/tty.4.md)

## 历史

`sigvec` 系统调用首次出现于 4.2BSD。在 4.3BSD 中被重新实现为 sigaction(2) 的包装。

## 缺陷

本手册页仍然令人困惑。
