Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >当你在 Linux 上启动一个进程时会发生什么?

当你在 Linux 上启动一个进程时会发生什么?

作者头像
企鹅号小编
发布于 2018-02-02 09:13:03
发布于 2018-02-02 09:13:03
1.1K0
举报
文章被收录于专栏:编程编程

英文:Julia Evans,编译:Linux中国 / jessie-pang

linux.cn/article-9256-1.html

本文是关于 fork 和 exec 是如何在 Unix 上工作的。你或许已经知道,也有人还不知道。几年前当我了解到这些时,我惊叹不已。

我们要做的是启动一个进程。我们已经在博客上讨论了很多关于系统调用的问题,每当你启动一个进程或者打开一个文件,这都是一个系统调用。所以你可能会认为有这样的系统调用:

start_process(["ls","-l","my_cool_directory"])

这是一个合理的想法,显然这是它在 DOS 或 Windows 中的工作原理。我想说的是,这并不是 Linux 上的工作原理。但是,我查阅了文档,确实有一个 posix_spawn 的系统调用基本上是这样做的,不过这不在本文的讨论范围内。

fork 和 exec

Linux 上的 posix_spawn 是通过两个系统调用实现的,分别是 fork 和 exec(实际上是 execve),这些都是人们常常使用的。尽管在 OS X 上,人们使用 posix_spawn,而 fork 和 exec 是不提倡的,但我们将讨论的是 Linux。

Linux 中的每个进程都存在于“进程树”中。你可以通过运行 pstree 命令查看进程树。树的根是 init,进程号是 1。每个进程(init 除外)都有一个父进程,一个进程都可以有很多子进程。

所以,假设我要启动一个名为 ls 的进程来列出一个目录。我是不是只要发起一个进程 ls 就好了呢?不是的。

我要做的是,创建一个子进程,这个子进程是我(me)本身的一个克隆,然后这个子进程的“脑子”被吃掉了,变成 ls。

开始是这样的:

myparent

|-me

然后运行 fork(),生成一个子进程,是我(me)自己的一份克隆:

myparent

|-me

|--cloneofme

然后我让该子进程运行 exec("ls"),变成这样:

myparent

|-me

|--ls

当 ls 命令结束后,我几乎又变回了我自己:

myparent

|-me

|--ls(zombie)

在这时 ls 其实是一个僵尸进程。这意味着它已经死了,但它还在等我,以防我需要检查它的返回值(使用 wait 系统调用)。一旦我获得了它的返回值,我将再次恢复独自一人的状态。

myparent

|-me

fork 和 exec 的代码实现

如果你要编写一个 shell,这是你必须做的一个练习(这是一个非常有趣和有启发性的项目。Kamal 在 Github 上有一个很棒的研讨会:https://github.com/kamalmarhubi/shell-workshop)。

事实证明,有了 C 或 Python 的技能,你可以在几个小时内编写一个非常简单的 shell,像 bash 一样。(至少如果你旁边能有个人多少懂一点,如果没有的话用时会久一点。)我已经完成啦,真的很棒。

这就是 fork 和 exec 在程序中的实现。我写了一段 C 的伪代码。请记住,fork 也可能会失败哦。

intpid=fork();

// 我要分身啦

// “我”是谁呢?可能是子进程也可能是父进程

if(pid==){

// 我现在是子进程

// “ls” 吃掉了我脑子,然后变成一个完全不一样的进程

exec(["ls"])

}elseif(pid== -1){

// 天啊,fork 失败了,简直是灾难!

}else{

// 我是父进程耶

// 继续做一个酷酷的美男子吧

// 需要的话,我可以等待子进程结束

}

上文提到的“脑子被吃掉”是什么意思呢?

进程有很多属性:

打开的文件(包括打开的网络连接)

环境变量

信号处理程序(在程序上运行 Ctrl + C 时会发生什么?)

内存(你的“地址空间”)

寄存器

可执行文件(/proc/$pid/exe)

cgroups 和命名空间(与 Linux 容器相关)

当前的工作目录

运行程序的用户

其他我还没想到的

当你运行 execve 并让另一个程序吃掉你的脑子的时候,实际上几乎所有东西都是相同的! 你们有相同的环境变量、信号处理程序和打开的文件等等。

唯一改变的是,内存、寄存器以及正在运行的程序,这可是件大事。

为何 fork 并非那么耗费资源(写入时复制)

你可能会问:“如果我有一个使用了 2GB 内存的进程,这是否意味着每次我启动一个子进程,所有 2 GB 的内存都要被复制一次?这听起来要耗费很多资源!”

事实上,Linux 为 fork() 调用实现了写时复制copy on write,对于新进程的 2GB 内存来说,就像是“看看旧的进程就好了,是一样的!”。然后,当如果任一进程试图写入内存,此时系统才真正地复制一个内存的副本给该进程。如果两个进程的内存是相同的,就不需要复制了。

为什么你需要知道这么多

你可能会说,好吧,这些细节听起来很厉害,但为什么这么重要?关于信号处理程序或环境变量的细节会被继承吗?这对我的日常编程有什么实际影响呢?

有可能哦!比如说,在 Kamal 的博客上有一个很有意思的bug。它讨论了 Python 如何使信号处理程序忽略了 SIGPIPE。也就是说,如果你从 Python 里运行一个程序,默认情况下它会忽略 SIGPIPE!这意味着,程序从 Python 脚本和从 shell 启动的表现会有所不同。在这种情况下,它会造成一个奇怪的问题。

所以,你的程序的环境(环境变量、信号处理程序等)可能很重要,都是从父进程继承来的。知道这些,在调试时是很有用的。

看完本文有收获?请分享给更多人

关注「Linux 爱好者」,提升Linux技能

本文来自企鹅号 - 程序员的那些事媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文来自企鹅号 - 程序员的那些事媒体

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
说一说 Linux 进程控制
在上一则发表的关于 Linux 的文章中,叙述了 Linux 的相关概念,其中就包括进程的资源,进程的状态,以及进程的属性等相关内容,在本则教程中,将着重叙述 Linux 进程管理的内容,其中就包括 Linux 进程的创建,进程的终止,进程的等待相关内容。
wenzid
2021/07/20
5940
说一说 Linux 进程控制
nginx源码阅读(5)Master进程浅析
众所周如,Nginx是多进程架构。有1个master进程和N个worker进程,一般N等于cpu的核数。另外, 和文件缓存相关,还有cache manager和cache loader进程。
golangLeetcode
2022/08/02
1.9K0
nginx源码阅读(5)Master进程浅析
Linux进程编程
功能:创建一个与原来进程几乎完全相同的进程,即两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。一个进程调用fork函数后,系统先给新的进程分配资源,例如,存储数据和代码的空间。然后把原来的进程所有值都复制到新的进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
Marigold
2022/06/17
7.9K0
Linux进程编程
【Linux】Linux进程控制>进程创建&&进程终止&&进程等待&&进程程序替换
在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程
用户10925563
2024/06/04
5450
【Linux】Linux进程控制>进程创建&&进程终止&&进程等待&&进程程序替换
Linux进程控制
返回值:自进程中返回0,父进程返回子进程id,出错返回-1。 进程拥有独立性,fork之后就变成了两个程序,父子进程共享后边的代码。 那么为什么给父进程返回的就是子进程的pid,而给子进程返回的就是0呢? 就好比孩子只能有一个亲生的父亲,而一个父亲可以拥有很多亲生孩子,每个孩子都是独立不同的。 fork函数是在什么时候创建的子进程呢?
有礼貌的灰绅士
2023/03/28
2.9K0
Linux进程控制
Linux系统-进程控制
Linux进程控制 零、前言 一、进程创建 1、fork函数 2、fork返回值 写时拷贝 3、fork用法 4、fork失败 二、进程终止 1、退出码 2、退出方法 1) 调用_exit函数 2)调用exit函数 3)main函数return 4)异常退出 3、理解终止 三、进程等待 1、等待方法 2、获取status 3、理解等待 四、进程替换 1、替换原理 2、替换方法 五、实现简易shell 零、前言 前篇我们讲解学习了关于进程的概念知识,本章主要讲解关于进程的控制,深入学习进程 一、进程创建
用户9645905
2022/11/30
1.5K0
Linux系统-进程控制
linux系统编程之进程(二):fork函数相关总结
该文介绍了Linux系统下进程的创建、进程的终止、以及终止进程可能产生的后果。另外,还介绍了Linux系统下fork函数的使用,以及和vfork函数之间的区别。
s1mba
2018/01/03
2.9K0
linux系统编程之进程(二):fork函数相关总结
Linux进程控制
进程是操作系统中的一个重要概念,它是一个程序的一次执行过程,程序是进程的一种静态描述,系统中运行的每一个程序都是在它的进程中运行的。
xxpcb
2020/08/04
2K0
【linux】进程等待与进程替换
任何子进程,在退出的情况下,一般必须要被父进程进行等待。进程在退出的时候,如果父进程不管不顾,退出进程,状态Z(僵尸状态),内存泄漏
用户11029103
2024/11/16
1760
【linux】进程等待与进程替换
【Linux】Linux进程控制 --- 进程创建、终止、等待、替换、shell派生子进程的理解…
1. 在调用fork函数之后,当执行的程序代码转移到内核中的fork代码后,内核需要分配新的内存块和内核数据结构给子进程,内核数据结构包括PCB、mm_struct和页表,然后构建起映射关系,同时将父进程内核数据结构中的部分内容拷贝到子进程,并且内核还会将子进程添加到系统进程列表当中,最后内核空间中的fork代码执行完毕,操作系统中也就已经创建出来了子进程,最后返回用户空间,父子进程执行程序fork之后的剩余代码。
举杯邀明月
2023/04/12
15K0
【Linux】Linux进程控制 --- 进程创建、终止、等待、替换、shell派生子进程的理解…
深入了解 Node 的多进程服务
我们现在已经知道了Node是单线程运行的,这表示潜在的错误有可能导致线程崩溃,然后进程也会随着退出,无法做到企业追求的稳定性;另一方面,单进程也无法充分多核CPU,这是对硬件本身的浪费。Node社区本身也意识到了这一问题,于是从0.1版本就提供了child_process模块,用来提供多进程的支持。
用户8921923
2022/10/24
7870
进程详解(1)——可能是最深入浅出的进程学习笔记
原文地址:http://www.cnblogs.com/jacklu/p/5317406.html
用户7043923
2020/03/12
5140
【Linux】万字解读<进程控制>:创建&中止&等待&替换
YY的秘密代码小屋
2024/09/11
1300
【Linux】万字解读<进程控制>:创建&中止&等待&替换
Linux 阻碍国产操作系统进程?
简单来讲,进程就是运行中的程序。更进一步,在用户空间中,进程是加载器根据程序头提供的信息将程序加载到内存并运行的实体。
CSDN技术头条
2019/05/09
2K0
Linux 阻碍国产操作系统进程?
【Linux】深入理解进程管理与高效运用
        进程是正在运行的程序实例,在Linux内核中,进程被称为任务,例如内核线程与用户线程等。
小文要打代码
2025/03/18
1580
csapp 第八章 异常控制流 读书笔记
的过渡称为控制转移(control transfer)。这样的控制转移序列叫做处理器的控制流(flow of control or control flow) control flow的突变(
BBuf
2023/08/22
3700
csapp 第八章 异常控制流 读书笔记
【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换
可以发现,错误码为0时,代表代码正常执行完毕,所以我们平时主函数里的return 都是return 0
aosei
2024/01/23
3920
【Linux】进程控制:理解什么是进程创建,进程终止,进程等待 | 进程替换
[apue] 进程控制那些事儿
在介绍进程的创建、启动与终止之前,首先了解一下进程的唯一标识——进程 ID,它是一个非负整数,在系统范围内唯一,不过这种唯一是相对的,当一个进程消亡后,它的 ID 可能被重用。不过大多数 Unix 系统实现延迟重用算法,防止将新进程误认为是使用同一 ID 的某个已终止的进程,下面这个例子展示了这一点:
海海
2024/03/30
4170
[apue] 进程控制那些事儿
Linux 进程管理
Linux是一个多用户多任务的操作系统。多用户是指多个用户可以在同一时间使用同一个linux系统;多任务是指在Linux下可以同时执行多个任务,更详细的说,linux采用了分时管理的方法,所有的任务都放在一个队列中,操作系统根据每个任务的优先级为每个任务分配合适的时间片,每个时间片很短,用户根本感觉不到是多个任务在运行,从而使所有的任务共同分享系统资源,因此linux可以在一个任务还未执行完时,暂时挂起此任务,又去执行另一个任务,过一段时间以后再回来处理这个任务,直到这个任务完成,才从任务队列中去除。这就是多任务的概念。 上面说的是单CPU多任务操作系统的情形,在这种环境下,虽然系统可以运行多个任务,但是在某一个时间点,CPU只能执行一个进程,而在多CPU多任务的操作系统下,由于有多个CPU,所以在某个时间点上,可以有多个进程同时运行。 进程的的基本定义是:在自身的虚拟地址空间运行的一个独立的程序,从操作系统的角度来看,所有在系统上运行的东西,都可以称为一个进程。
黄规速
2022/04/14
4.2K0
Linux 进程管理
超硬核,进程在内存中的样子!以及进程的一生
进一步讲,进程是在用户空间中,加载器根据程序头提供的信息,将程序加载到内存并运行的实体。
用户8639654
2021/08/27
8730
相关推荐
说一说 Linux 进程控制
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档