diff --git a/docs/16.md b/docs/16.md index 6997422d18c8c7efd0e1c9a26e3ab82afca271b6..0b92d71d6b9105b8f9fa14674c09ce876a59115f 100644 --- a/docs/16.md +++ b/docs/16.md @@ -4,13 +4,13 @@ ## 一句警告 -进程分叉是一个非常强大(非常危险)的工具。如果你陷入困境并造成一个叉炸弹(本页后面会有解释),**你可以关闭整个系统**。为了减少这种情况,可以通过在命令行中键入`ulimit -u 40`将最大进程数限制为较小的数量,例如 40。请注意,此限制仅适用于用户,这意味着如果您分叉炸弹,那么您将无法杀死刚刚创建的所有进程,因为调用`killall`需要 shell 来 fork()...具有讽刺意味的权利?那么我们可以做些什么呢。一种解决方案是在另一个用户(例如 root)之前生成另一个 shell 实例,然后从那里杀死进程。另一种方法是使用内置的`exec`命令来杀死所有用户进程(小心你只有一次射击)。最后你可以重启系统:) +进程分叉是一个非常强大(非常危险)的工具。如果你陷入困境并造成一个分叉炸弹(本页后面会有解释),**你可能关闭整个系统**。为了减少这种情况,可以通过在命令行中键入`ulimit -u 40`将最大进程数限制为较小的数量,例如 40。请注意,此限制仅适用于用户,这意味着如果您分叉了炸弹,那么您将无法杀死刚刚创建的所有进程,因为调用`killall`需要 shell 来 `fork()`...很讽刺对吗?那么我们可以做些什么呢。一种解决方案是在另一个用户(例如 root)之前生成另一个 shell 实例,然后从那里杀死进程。另一种方法是使用内置的`exec`命令来杀死所有用户进程(小心你只有一次机会)。最后你可以重启系统:) -在测试 fork()代码时,请确保您对所涉及的计算机具有 root 和/或物理访问权限。如果您必须远程处理 fork()代码,请记住 **kill -9 -1** 将在紧急情况下为您节省时间。 +在测试`fork()`代码时,请确保您对所涉及的计算机具有 root 和/或物理访问权限。如果您必须远程处理`fork()`代码,请记住`kill -9 -1`将在紧急情况下为您节省时间。 -TL; DR:如果您没有为此做好准备,那么**非常**会很危险。 **你被警告过了。** +太长不看:如果您没有为此做好准备,那么会**非常**危险。**警告过你了**。 -## 叉子介绍 +## 分叉介绍 ## fork 做什么? @@ -160,7 +160,7 @@ int main(int argc, char**argv) { `system`调用将 fork,执行参数传递的命令,原始父进程将等待此操作完成。这也意味着`system`是一个阻塞调用:在`system`退出进程之前,父进程无法继续。这可能有用也可能没用。此外,`system`实际上创建了一个 shell,然后给出了字符串,这比直接使用`exec`更开销。标准 shell 将使用`PATH`环境变量来搜索与命令匹配的文件名。对于许多简单的 run-this-command 问题,使用系统通常就足够了,但很快就会成为更复杂或微妙问题的限制,它隐藏了 fork-exec-wait 模式的机制,所以我们鼓励你学习和使用`fork` `exec`和`waitpid`代替。 -## 什么是最愚蠢的叉子例子? +## 什么是最愚蠢的分叉例子? 一个稍微愚蠢的例子如下所示。它会打印什么?尝试使用程序的多个参数。 diff --git a/docs/17.md b/docs/17.md index 1c6860a59f924a1b078fedf305f86525cdb3efbf..58f990f24d34e78e903b795bcbae08af2acfe086 100644 --- a/docs/17.md +++ b/docs/17.md @@ -30,7 +30,7 @@ int main() { * execl:用/ bin / ls 替换程序映像并调用其 main()方法 * perror:我们不希望到达这里 - 如果我们这样做,那么 exec 就失败了。 -## 微妙的叉子虫 +## 微妙的分叉虫 这段代码出了什么问题 diff --git a/docs/42.md b/docs/42.md index edfa7e42214d906e9a6797c63e1e54416a8b0335..698f460ad1f8fbb37014c64fb13d813ec92277f7 100644 --- a/docs/42.md +++ b/docs/42.md @@ -47,7 +47,7 @@ ## 餐饮哲学家 -Dining Philosophers 问题是一个经典的同步问题。想象一下,我邀请 N(让我们说 5 位)哲学家吃饭。我们将坐在一张桌子上,用五根筷子(每个哲学家之间一个)。哲学家在想要吃饭或思考之间交替。吃饭的哲学家必须在他们的位置两侧拾起两根筷子(原始问题要求每个哲学家都有两把叉子)。然而,这些筷子与他的邻居分享。 +Dining Philosophers 问题是一个经典的同步问题。想象一下,我邀请 N(让我们说 5 位)哲学家吃饭。我们将坐在一张桌子上,用五根筷子(每个哲学家之间一个)。哲学家在想要吃饭或思考之间交替。吃饭的哲学家必须在他们的位置两侧拾起两根筷子(原始问题要求每个哲学家都有两把分叉)。然而,这些筷子与他的邻居分享。 ![5DiningPhilosophers](img/faa7ac1f5f07a2ceee3dcc5057f329c6.jpg) diff --git a/docs/43.md b/docs/43.md index abb63fe51e710329ecc5a6c2d1ef2fdbe9677fee..ea41553aea59267d70f4ee82095b7c4f36ce16c5 100644 --- a/docs/43.md +++ b/docs/43.md @@ -71,14 +71,14 @@ void* philosopher(void* forks){ 这可以防止死锁,因为没有循环等待!没有哲学家必须等待任何其他哲学家。 -高级仲裁者解决方案是实施一个类,确定哲学家的分叉是否在仲裁员的掌握之中。如果他们是,他们把它们交给哲学家,让他吃,并把叉子拿回来。这有额外的好处,可以让多个哲学家同时吃。 +高级仲裁者解决方案是实施一个类,确定哲学家的分叉是否在仲裁员的掌握之中。如果他们是,他们把它们交给哲学家,让他吃,并把分叉拿回来。这有额外的好处,可以让多个哲学家同时吃。 ### 问题: * 这些解决方案很慢 * 他们有一个单点的失败,仲裁员使其成为瓶颈 * 仲裁者也需要公平,并能够在第二个解决方案中确定死锁 -* 在实际系统中,仲裁员倾向于将重复的叉子交给那些因为过程调度而吃的哲学家 +* 在实际系统中,仲裁员倾向于将重复的分叉交给那些因为过程调度而吃的哲学家 ## 离开桌子(Stallings 的解决方案) @@ -96,7 +96,7 @@ void* philosopher(void* forks){ 这是 Dijkstra 的解决方案(他是在考试中提出这个问题的人)。为什么第一个解决方案陷入僵局? Dijkstra 认为最后一个拿起左叉的哲学家(使解决方案陷入僵局)应该选择他的权利。他用数字 1..n 来完成它,并告诉每个哲学家拿起他的较低数字叉。 -让我们再次遇到死锁情况。每个人都试图先拿起他们的低号码叉。哲学家 1 获得分叉 1,哲学家 2 获得分叉 2,依此类推,直到我们到达哲学家 n。他们必须在 fork 1 和 n 之间进行选择。 fork 1 已被哲学家 1 所阻挡,所以他们无法拿起那个叉子,这意味着他不会拿起叉子。我们已经打破了循环等待!意味着死锁是不可能的。 +让我们再次遇到死锁情况。每个人都试图先拿起他们的低号码叉。哲学家 1 获得分叉 1,哲学家 2 获得分叉 2,依此类推,直到我们到达哲学家 n。他们必须在 fork 1 和 n 之间进行选择。 fork 1 已被哲学家 1 所阻挡,所以他们无法拿起那个分叉,这意味着他不会拿起分叉。我们已经打破了循环等待!意味着死锁是不可能的。 ### Problems: