> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/4.3-bsd-unix-cao-zuo-xi-tong-she-ji-yu-shi-xian/di-yi-bu-fen-gai-lan/3.2.-xi-tong-diao-yong.md).

# 3.2 系统调用

（时钟处理之外）最频繁的内核陷阱是做系统调用的请求。良好的性能要求内核把接应和分发系统调用的开销降到最低。系统调用分发程序为启动一次系统调用要做以下工作：

* 查出该系统调用的参数个数
* 校验参数位于有效的用户地址，然后把它们从用户进程复制进内核
* 为系统调用被中断的可能性做准备
* 调用执行该系统调用的具体内核例程

**结果处理**

系统调用最终无论成功与否都要返回到调用进程。在 VAX 上，成功与否由用户进程程序状态长字中的进位位指示：为零则返回成功，否则失败。在 VAX 和许多其他机器上，C 函数的返回值经通用寄存器 0 传回。系统调用成功时，内核的系统调用处理程序用一个返回值替换该寄存器的保存值。调用失败时，处理程序从内核变量 `u.u_error` 取一个错误码（由该系统调用更深的内核例程留在那里）放进寄存器——这是内核有意修改进程状态的一处。系统调用的 C 库例程把这个值移到全局变量 `errno`，并把寄存器设为 −1。调用进程应当察觉寄存器的值，然后在出错时检查 `errno`。这套涉及进位位和全局变量 `errno` 的机制，是 PDP-11 时代留下的历史产物。

系统调用失败返回有两种：内核系统调用处理例程发现错误的，以及系统调用被中断的。系统调用在为等待一个可能很久都不会出现的事件（如等待终端输入）而交出处理器之后，可能被一个中途到达的信号打断。信号能够投递之前，必须先通过一个非局部跳转回到分发程序来中止系统调用。进程设置信号处理程序时，必须指明被它中断的系统调用应当重启，还是以“系统调用被中断”错误中止。

非局部跳转发生时，分发程序通过检查一个每进程全局变量来决定怎么做。如果进程请求中止系统调用，分发程序就按前述方式安排返回错误。如果系统调用要重启，分发程序则计算如何让进程的程序计数器指向引发系统调用陷入内核的那条机器指令。这一步计算必不可少，因为系统调用陷入时保存的程序计数器值指向系统调用结果处理代码的开头。分发程序用新算出的值替换保存的程序计数器值。进程下次被调度时，将被强制处理该信号；从信号处理程序返回后，进程将在分发程序给出的程序计数器值处恢复执行，于是会重新执行同一系统调用。

回退程序计数器来重启系统调用有一些隐含要求。最重要的是内核必须确保没有改动任何输入参数。其次，必须确保系统调用尚未部分完成。例如，如果已从终端读入半行，read 必须以短计数返回；若重启调用，半读的行将被不当覆盖。

**从系统调用返回**

系统调用运行期间，可能有信号投递给进程，也可能别的进程取得了更高的调度优先级。系统调用完成后，分发程序检查这两件事是否发生。

分发程序先检查已投递的信号。这包括导致系统调用中止的信号，也包括系统调用进行途中到达、但被扣住等调用完成的信号。默认或经显式设置而被忽略的信号从不投递给进程。有默认动作的信号，在进程再次运行之前先执行该动作（即视情况杀死或停止进程）。若信号将被捕获（且当前未被屏蔽），分发程序就安排调用相应的信号处理程序，而不是让进程直接从系统调用返回。只有处理程序正常返回后，进程才在系统调用返回处（若系统调用将重启，则在执行处）恢复执行。

检查过已投递的信号后，分发程序再看是否有别的进程优先级高于当前进程。若有，分发程序调用上下文切换例程，安排高优先级进程运行。当前进程晚些时候取得最高优先级后，将从系统调用返回用户进程，恢复执行。

如果进程请求了剖析，分发程序计算系统调用花费的时间：取进程进入和离开分发程序之间记在它名下的系统时间之差。这段时间记到用户进程中发起系统调用的那个例程头上。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://book.bsdcn.org/4.3-bsd-unix-cao-zuo-xi-tong-she-ji-yu-shi-xian/di-yi-bu-fen-gai-lan/3.2.-xi-tong-diao-yong.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
