# 四个系统调用

《直观感受》章节已经提供了一个样例程序运行三个系统调用。下面还是再介绍一点。

## fork系统调用

**fork系统调用**用于创建子进程，内核需要为子进程分配一块独立的内存，将父进程的地址空间、用户态堆栈完全拷贝至子进程的内存中（温馨提示，不要用结构体整体赋值！！！因为这是老版本c语言未定义行为），并为子进程分配独立的进程控制块，完成对子进程的进程控制块的设置。

若子进程创建成功，则对于父进程，该系统调用的返回值为子进程的 pid ，对于子进程，其返回值为 0 ；若子进程创建失败，该系统调用的返回值为 -1。

```
pid_t fork();
```

## Exec系统调用

相比于fork，我们可能更少去用exec系统调用，但实际上他们常常配合使用。wikipedia是这样介绍exec的：

> In [computing](https://en.wikipedia.org/wiki/Computing), **exec** is a functionality of an [operating system](https://en.wikipedia.org/wiki/Operating_system) that runs an [executable file](https://en.wikipedia.org/wiki/Executable_file) in the context of an already existing [process](https://en.wikipedia.org/wiki/Process_\(computing\)), replacing the previous executable. This act is also referred to as an **overlay**. It is especially important in [Unix-like](https://en.wikipedia.org/wiki/Unix-like) systems, although it exists elsewhere. As no new process is created, the [process identifier](https://en.wikipedia.org/wiki/Process_identifier) (PID) does not change, but the [machine code](https://en.wikipedia.org/wiki/Machine_code), [data](https://en.wikipedia.org/wiki/Data_\(computing\)), [heap](https://en.wikipedia.org/wiki/Heap_\(programming\)), and [stack](https://en.wikipedia.org/wiki/Run-time_stack) of the process are replaced by those of the new program.
>
> The *exec* call is available for many [programming languages](https://en.wikipedia.org/wiki/Programming_language) including [compilable](https://en.wikipedia.org/wiki/Compiler) languages and some [scripting languages](https://en.wikipedia.org/wiki/Scripting_language). In [OS command interpreters](https://en.wikipedia.org/wiki/Operating_system_shell), the exec [built-in command](https://en.wikipedia.org/wiki/Shell_builtin) replaces the shell process with the specified program.[\[1\]](https://en.wikipedia.org/wiki/Exec_\(system_call\)#cite_note-bashref-1)

在Linux中，exec的实现比较复杂，在这里，我们实现一个简化版本。我们的exec把一个新的程序**装载到当前进程中，替换掉当前进程**。

在我们的实验中，exec系统调用接受两个参数：`secstart`和`secnum`。第一个参数表明新程序在磁盘中的位置，第二个参数表明新程序在磁盘中占据的扇区数。

{% hint style="danger" %}
challenge5：你是否可以完善你的exec，第三个参数接受变长参数，用来模拟带有参数程序执行。

举个例子，在shell里面输入cat a.txt b.txt，实际上shell会fork出一个新的shell（假设称为shell0），并执行exec("cat", "a.txt","b.txt")运行cat程序，覆盖shell0的进程。

不必完全参照Unix，可以有自己的思考与设计。
{% endhint %}

## sleep系统调用

sleep系统调用用于进程主动阻塞自身，内核需要将该进程由 RUNNING 状态转换为 BLOCKED 状态，设置 该进程的 SLEEP 时间片，并切换运行其他 RUNNABLE 状态的进程。

```
int sleep(uint32_t time);
```

## exit系统调用

exit系统调用用于进程主动销毁自身，内核需要将该进程由 RUNNING 状态转换为 DEAD 状态，回收分配 给该进程的内存、进程控制块等资源，并切换运行其他 RUNNABLE 状态的进程。我们实验中实现的是一个简化版本，不需要参数（你用C语言使用\`exit()\`的时候是需要一个参数的）。

```
int exit();
```

{% hint style="info" %}
exercise8：请用fork，sleep，exit自行编写一些并发程序，运行一下，贴上你的截图。（自行理解，不用解释含义，帮助理解这三个函数）
{% endhint %}


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://changanyyy.gitbook.io/oslab/cao-zuo-xi-tong-lab3-zuo-you-feng-yuan-tiao-du-qi/ji-chu-zhi-shi/si-ge-xi-tong-tiao-yong.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
