# 进程,第 1 部分:简介
> 原文:[Processes, Part 1: Introduction](https://github.com/angrave/SystemProgramming/wiki/Processes%2C-Part-1%3A-Introduction)
> 校验:[飞龙](https://github.com/wizardforcel)
> 自豪地采用[谷歌翻译](https://translate.google.cn/)
## 概览
进程是运行中的程序(大致)。进程也只是这个运行中的计算机程序的一个实例。进程有很多东西可供使用。在每个程序启动时,您将获得一个进程,但每个程序可以创建更多进程。实际上,您的操作系统只启动了一个进程,所有其他进程都是由它分叉的 - 所有这些都是在启动时在背后完成的。
## 好吧,但是什么是程序?
程序通常包含以下内容
+ 二进制格式:告诉操作系统二进制中的哪些位集是什么 -- 哪个部分是可执行的,哪些部分是常量,要包括哪些库等。
+ 一套机器指令
+ 表示从哪条指令开始的数字
+ 常量
+ 要链接的库以及在何处填写这些库的地址
## 最开始
当您的操作系统在 Linux 机器上启动时,会创建一个名为`init.d`的进程。该进程是个处理信号和中断的特殊进程,和某些内核元素的持久性模块。无论何时想要创建一个新进程,都可以调用`fork`(将在后面的部分中讨论)并使用另一个函数来加载另一个程序。
## 进程隔离
进程非常强大,但它们是隔离的!这意味着默认情况下,任何进程都无法与另一个进程通信。这非常重要,因为如果你有一个大型系统(比方说 EWS),那么你希望某些进程拥有比普通用户更高的权限(监控,管理员),并且当然不希望普通用户通过有意或无意修改进程,能够搞崩整个系统。
如果我在两个不同的终端上运行以下代码,
```
int secrets; //maybe defined in the kernel or else where
secrets++;
printf("%d\n", secrets);
```
正如你猜测的那样,它们都打印出 1 而不是 2。即使我们改变了代码来做一些真正的黑魔法(除了直接读取内存),也没有办法改变另一个进程的状态(好吧,也许 [DirtyCow](https://en.wikipedia.org/wiki/Dirty_COW) 可以,但这有点太深入了)。
## 进程内容
## 内存布局
![Address Space](https://img.kancloud.cn/fd/db/fddb533cdc1b26cc4835c87bba1124d0_500x365.jpg)
当进程启动时,它会获得自己的地址空间。意味着每个进程得到:
* **一个栈**。栈是存储自动变量和函数调用返回地址的位置。每次声明一个新变量时,程序都会向下移动栈指针来保留变量的空间。栈的这一部分是可写的但不可执行。如果栈增长得太远(意味着它增长超出预设边界或与堆相交),您将获得栈溢出,最有可能导致 SEGFAULT 或类似的东西。**栈默认静态分配,意味着只有一定数量的可写空间**。
* **堆**。堆是一个扩展的内存区域。如果你想分配一个大对象,它就在这里。堆从文本段的顶部开始向上增长(有时当你调用`malloc`它要求操作系统向上推动堆边界)。此区域也是可写但不可执行。如果系统受限制或者地址耗尽(在 32 位系统上更常见),则可能会耗尽堆内存。
* **数据段**包含所有全局变量。此部分从 Text 段的末尾开始,并且大小是静态的,因为在编译时已知全局变量。这部分是可写的但不是可执行的,这里没有太过花哨的其他任何东西。
* **文本段**。可以说,这是地址中最重要的部分。这是存储所有代码的地方。由于汇编代码编译为 1 和 0,因此这是存储 1 和 0 的地方。程序计数器在该段中移动来执行指令,并向下一条指令移动。请务必注意,这是代码中唯一的可执行部分。如果您尝试在运行时更改代码,很可能会出现段错误(有很多方法可以解决它,但只是假设它是段错误)。
* 为什么不从零开始?它在这个课程的[范围](https://en.wikipedia.org/wiki/Address_space_layout_randomization)之外,但它是为了安全。
## 进程 ID(PID)
为了跟踪所有这些进程,您的操作系统为每个进程提供一个编号,该进程称为 PID,即进程 ID。 进程也有一个 ppid,它是父进程 ID 的缩写。 每个进程都有一个父进程,该父进程可以是`init.d`。
进程也可以包含:
+ 运行状态 -- 进程是否正在准备,运行,停止,终止等。
+ 文件描述符 -- 整数到实际设备(文件,USB 记忆棒,套接字)的映射列表
+ 权限 -- 正在运行文件的用户以及进程所属的组。 然后,该进程只对这个用户或组是可接受的,就像打开用户已经设为排他的文件一样。 有一些技巧可以使程序不成为启动该程序的用户,即`sudo`接受一个由用户启动的程序并以`root`身份执行该程序。
+ 参数 -- 字符串列表,告诉您的程序要在哪些参数下运行。
+ 环境列表 -- 可以修改的格式为`NAME=VALUE`的字符串列表。
- UIUC CS241 系统编程中文讲义
- 0. 简介
- #Informal 词汇表
- #Piazza:何时以及如何寻求帮助
- 编程技巧,第 1 部分
- 系统编程短篇小说和歌曲
- 1.学习 C
- C 编程,第 1 部分:简介
- C 编程,第 2 部分:文本输入和输出
- C 编程,第 3 部分:常见问题
- C 编程,第 4 部分:字符串和结构
- C 编程,第 5 部分:调试
- C 编程,复习题
- 2.进程
- 进程,第 1 部分:简介
- 分叉,第 1 部分:简介
- 分叉,第 2 部分:Fork,Exec,等等
- 进程控制,第 1 部分:使用信号等待宏
- 进程复习题
- 3.内存和分配器
- 内存,第 1 部分:堆内存简介
- 内存,第 2 部分:实现内存分配器
- 内存,第 3 部分:粉碎堆栈示例
- 内存复习题
- 4.介绍 Pthreads
- Pthreads,第 1 部分:简介
- Pthreads,第 2 部分:实践中的用法
- Pthreads,第 3 部分:并行问题(奖金)
- Pthread 复习题
- 5.同步
- 同步,第 1 部分:互斥锁
- 同步,第 2 部分:计算信号量
- 同步,第 3 部分:使用互斥锁和信号量
- 同步,第 4 部分:临界区问题
- 同步,第 5 部分:条件变量
- 同步,第 6 部分:实现障碍
- 同步,第 7 部分:读者编写器问题
- 同步,第 8 部分:环形缓冲区示例
- 同步复习题
- 6.死锁
- 死锁,第 1 部分:资源分配图
- 死锁,第 2 部分:死锁条件
- 死锁,第 3 部分:餐饮哲学家
- 死锁复习题
- 7.进程间通信&调度
- 虚拟内存,第 1 部分:虚拟内存简介
- 管道,第 1 部分:管道介绍
- 管道,第 2 部分:管道编程秘密
- 文件,第 1 部分:使用文件
- 调度,第 1 部分:调度过程
- 调度,第 2 部分:调度过程:算法
- IPC 复习题
- 8.网络
- POSIX,第 1 部分:错误处理
- 网络,第 1 部分:简介
- 网络,第 2 部分:使用 getaddrinfo
- 网络,第 3 部分:构建一个简单的 TCP 客户端
- 网络,第 4 部分:构建一个简单的 TCP 服务器
- 网络,第 5 部分:关闭端口,重用端口和其他技巧
- 网络,第 6 部分:创建 UDP 服务器
- 网络,第 7 部分:非阻塞 I O,select()和 epoll
- RPC,第 1 部分:远程过程调用简介
- 网络复习题
- 9.文件系统
- 文件系统,第 1 部分:简介
- 文件系统,第 2 部分:文件是 inode(其他一切只是数据...)
- 文件系统,第 3 部分:权限
- 文件系统,第 4 部分:使用目录
- 文件系统,第 5 部分:虚拟文件系统
- 文件系统,第 6 部分:内存映射文件和共享内存
- 文件系统,第 7 部分:可扩展且可靠的文件系统
- 文件系统,第 8 部分:从 Android 设备中删除预装的恶意软件
- 文件系统,第 9 部分:磁盘块示例
- 文件系统复习题
- 10.信号
- 过程控制,第 1 部分:使用信号等待宏
- 信号,第 2 部分:待处理的信号和信号掩码
- 信号,第 3 部分:提高信号
- 信号,第 4 部分:信号
- 信号复习题
- 考试练习题
- 考试主题
- C 编程:复习题
- 多线程编程:复习题
- 同步概念:复习题
- 记忆:复习题
- 管道:复习题
- 文件系统:复习题
- 网络:复习题
- 信号:复习题
- 系统编程笑话