Linux下的进程解析(level 2)

目录

引言

pid解析

/proc

系统调用

[fork :创建子进程](#fork :创建子进程)

执行流分析

父子进程谁先运行


引言

在当今的信息技术时代,操作系统作为计算机系统的核心组件,承担着资源管理、任务调度等重要职责。Linux作为一种开源、高性能的操作系统,受到了广大开发者和企业的青睐。深入了解Linux下的进程机制,对于我们更好地掌握系统运行原理、优化系统性能具有重要意义。接下来,让我们进一步探讨Linux下的进程解析,揭开进程管理的神秘面纱**。本文将着重介绍:pid与fork两个知识点,来深入解析进程。**

pid解析

进程id(PID)
父进程id(PPID)
pid与ppid在一个OS中一定是不重复的,这是每个进程的"身份证"

/proc

这是根目录下的一个内存级的文件夹。关掉linux之后,这个文件夹就不存在了。这个文件夹内部存储着进程的各个信息。

进程一般指:加载到内存的一个程序称作进程,因此我们写这样一个代码来模拟进程的执行。

通过ls这个目录,发现内部存在大量的数字命名的文件夹

这个文件夹的命名就是用pid命名的。

这就是内部的内容(查看家目录外的目录需要sudo职权)

以pid命名的目录文件内部包含什么内容?

在Linux操作系统中,每个进程都有一个唯一的进程标识符(PID),并且系统会在/proc文件系统中为每个运行中的进程创建一个以PID命名的目录。这些目录包含了关于进程的详细信息,以下是一些常见的文件和它们的内容:

  1. cmdline - 包含了启动进程时使用的完整命令行字符串。

  2. cwd - 一个指向进程当前工作目录的符号链接。

  3. environ - 包含了进程的环境变量。

  4. exe - 一个指向进程的可执行文件的符号链接。

  5. fd - 包含了进程打开的文件描述符的目录。每个文件描述符都映射到一个实际的文件或设备。

  6. maps - 显示了进程的内存映射,包括内存区域、访问权限、偏移量、设备信息和文件路径(如果有的话)。

  7. mem - 包含了进程的内存内容。通常,只有具有特权的用户才能访问这个文件。

  8. mounts - 包含了进程的挂载点信息。

  9. net - 包含了进程的网络相关的统计信息,如TCP套接字等。

  10. stat - 包含了进程的状态信息,如PID、父进程PID、用户ID、组ID、开始时间、CPU使用时间等。

  11. statm - 包含了进程使用的内存状态信息,如虚拟内存大小、Resident Set Size(RSS)等。

  12. status - 包含了进程的详细信息,如名称、状态、父进程ID、用户ID、组ID等。

  13. task - 包含了属于该进程的所有线程(或任务)的子目录。

这些文件提供了对进程内部状态的深入洞察,可以用于调试、性能分析和其他系统管理任务。需要注意的是,/proc文件系统是一个虚拟文件系统,它并不占用实际的磁盘空间,而是由内核在运行时动态生成。

在这些内容中,我们着重看两个文件:cwd exe

先将写的t1程序运行

ps axj 可以查看所有进程

&&表示执行两个独立的指令(也可以;)

现象分析:

1.为什么我们过滤t1进程,会出现两个进程信息呢?

这是因为grep本身就是一个程序,所以grep的进程信息也会出现。

2.这里的PID就是每个进程的身份信息,会出现在/proc文件中。我们可以打开它查看进程信息。

但是进程结束之后,将不会继续存在

我们将程序修改为死循环之后。

注:我们可以在底行模式查看手册 !man 3 sleep

再次运行程序,发现pid发生变化

查看这个pid

发现内部存在两个文件cwd(correct working directory)、exe(当前可执行程序的目录信息)

这些信息也解释了为什么我们touch一个文件,默认的路径是当前工作路径。

杀进程

kill -9 pid可以杀掉一个进程

系统调用

OS通过pcb来控制进程的运行,在linux下具体就是task_struct这个结构去控制的

ps可以遍历这个链表。我们都知道linux内核禁止访问,只能通过系统调用去访问对应的信息,因此访问pid与ppid这些信息只能通过接口去访问。

**getpid 、 getppid(**ppid:parent 父进程的pid)

父进程编号(ppid)不变:

bash本身是一个进程,负责解释命令行中的内容

命令行中的所有指令都是bash的子进程

bash只负责命令行的解释。进程出问题都只会影响bash的子进程

因此父进程ppid一直不变

linux下开发的c/cpp,如果调用了linux的系统调用接口,那么windows下不能直接运行

fork :创建子进程

返回值:给子进程返回0,给父进程返回子进程的pid

/return val调出返回值

代码:

现象:

发现程序并没有进入死循环,而是不断重复两个死循环的内容,这是为什么呢?

父进程的ppid就是bash(可见bash内部一定有fork机制)

子进程的ppid就是父进程

执行流分析

fork:分叉,将代码一分为二

它会产生两个进程,一个进程去执行第一个循环,另一个进程去执行第二个循环。两个进程分开跑。

问题:

1.为什么fork要给子进程返回0,给父进程返回子进程的pid?

2.一个函数如何做到返回两次的,如何理解?

3.一个变量为什么有不同的内容,本质是什么?

解析:

返回不同的返回值,是为区分不同的执行流、执行不同的代码块。一般而言,fork语句之后的代码共享

进程 = 内核数据结构 + data + 代码

这个pcb可以指向data + 代码

那子进程该执行怎么样的代码呢?

已知,子进程与父进程的代码在fork之后是共享的

为什么需要创建子进程呢?毫无疑问,对于不同的进程,我们存在不同的需求,因此得想办法让父子进程执行不同的代码块。这使得fork让父子存在不同的返回值。

如何做到的?

已知,进程具有独立性,父子进程并不会相互影响。

理解:QQ崩了不影响微信的使用!

进程的几大性质:

  1. 动态性:进程的动态性表现在进程的创建、执行和消亡是随时间变化的。进程的状态可以在运行、就绪、阻塞等状态之间转换。

  2. 并发性:多个进程可以在同一时间段内同时执行,这体现了操作系统的并发性。并发性是提高计算机系统资源利用率的关键特性。

  3. 异步性:每个进程按照自己的节奏独立运行,不受其他进程执行速度的影响。进程的异步性要求操作系统提供同步机制来协调进程间的操作。

  4. 结构性:进程通常由代码段、数据段、堆栈段等组成,这些段构成了进程的内存映像,体现了进程的结构性。

  5. 独立性:每个进程都有自己的地址空间、执行状态和系统资源,如文件描述符、信号处理等,进程之间不相互干扰。

  6. 交互性:进程之间可以通过进程间通信(IPC)机制进行数据交换和同步操作,如管道、消息队列、共享内存、信号量等。

  7. 可控性:操作系统可以控制进程的执行,包括启动、暂停、恢复和终止进程。进程调度器负责分配CPU时间给各个进程。

  8. 可见性:进程的创建、状态变化和资源使用情况可以通过系统提供的工具(如ps、top等)被用户或系统管理员观察到。

fork是一个函数,在函数的内部完成了创建子进程的工作。得到了子进程的PCB,父子进程都具有独立的PCB,因此互不影响。

可见,在return语句之前,函数就完成了子进程的创建。而子进程创建好了之后,后面的代码父子进程共享,也就是说return是父子进程共享的。

因此父进程可以得到自己的return,子进程也可以得到自己的return。

为什么返回值不同呢?---- 问题三:一个变量存在不同的内容

这是因为进程的写时拷贝!

内存划分:(内存中的代码和数据的辨析)

内存主要有四部分构成:

栈、堆、代码段(常量区)、数据段(静态区)

栈(Stack):用于存储临时变量、函数参数、返回地址等。这些数据通常是局部于函数调用的。

堆(Heap):用于动态分配内存,通常用于存储全局变量和动态分配的数据结构。

数据段(Data Segment):用于存储全局和静态变量,这些变量在程序启动时分配,并在程序运行期间持续存在。

代码段(Code Segment):包含程序的指令,通常是不变的。

当代码加载到内存中时,一般存储在代码段。而数据则是存储在其他三个区域

我们都知道,代码存储在代码段,是禁止修改的,那父子进程指向相同的代码但是却有不同的数据,这是因为数据不存储在代码段,数据是可以修改的。

共享代码并不影响独立性,因为代码是只读的,不允许修改。但是数据不一样!

因此子进程的pcb不能执行父进程的数据,而是得额外开辟自己的区域存储数据。

****子进程有自己单独的数据。虽然代码是一样的。但是id这个变量接收的数据是不一样的。所以cpu在计算时,通过公共的代码,访问不同的数据

这也可以解释进程的独立性:数据上的割裂导致进程在执行时,不会相互影响。

但是!直接给子进程开辟一份数据所占用的内存往往是不必要的。因为可能子进程和父进程访问的数据内容一致。这时候将会访问同一块内存当中的数据。

因此,如果子进程不做数据的修改,可以与父进程访问相同的数据,但是一旦子进程发生数据的修改,那么就要做拦截。只有当子进程想修改数据时,做拦截

只有对父进程的数据做修改,才会额外开辟一块内容,给子进程存放数据。让子进程去修改这部分数据。

这种技术称作:子进程在数据层面的写时拷贝

因此上述代码在return写入时,这就是对数据做了修改。因此在内存给子进程额外开辟了空间,让父子进程得到不同的返回值。

这也是为什么bash作为父进程,子进程出错不影响bash的原因。(数据的独立性)

父子进程谁先运行

这不是人为决定的,而是由调度器决定的。

调度器:选择一个进程放在cpu去运行

调度器:只有一块cpu,各个进程对于cpu是竞争关系,调度器尽量一碗水端平(运行时间平衡、不偏不漏)

相关推荐
用户9718356334662 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪4 小时前
linux 拷贝文件或目录到指定的位置
linux
大树8819 小时前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠19 小时前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质20 小时前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush420 小时前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行52020 小时前
Linux 11 动态监控指令top
linux
小宇宙Zz20 小时前
Maven依赖冲突
java·服务器·maven
Inhand陈工21 小时前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智21 小时前
ARP代理--工作原理
运维·网络·arp·arp代理