【Linux】进程(2):进程概念与操作理解

目录

[一 进程概念和基本操作](#一 进程概念和基本操作)

[1 什么是进程](#1 什么是进程)

[2 为什么要有进程](#2 为什么要有进程)

[3 怎么办----重点](#3 怎么办----重点)

[4 描述进程---PCB](#4 描述进程---PCB)

[二 task_struct](#二 task_struct)

内容分类

组织进程

[三 查看进程](#三 查看进程)

[1 /proc](#1 /proc)

[2 PID](#2 PID)

[3 crtl+c](#3 crtl+c)

[4 当前路径](#4 当前路径)

[5 指令](#5 指令)

chdir:改变当前的工作路径

getcwd:获取程序当前工作路径

[ps ajx:显示所有进程信息](#ps ajx:显示所有进程信息)

[四 父进程和子进程](#四 父进程和子进程)

getppid():得到父进程的PID

命令行启动的所有进程,父进程都是bash

[kill-9 PID](#kill-9 PID)

bash是如何创造子进程的?

父进程是如何创建子进程的?

fork的三个问题

问题1

问题2

[​编辑 问题3](#编辑 问题3)

如何利用fork建立多进程?


一 进程概念和基本操作

1 什么是进程

进程 = 内核数据结构(task_struct) + 自己的程序代码和数据

内核数据结构(struct task_struct):这是进程的 "学籍信息",包含了进程的 PID、优先级、内存地址、状态等元数据,是操作系统管理进程的核心。
程序的代码和数据:这是进程的 "本人",即被加载到内存中的可执行程序内容。

传统教材常说:"运行起来的程序就是进程" 或 "加载到内存的程序叫做进程"。但是这种说法只强调了 "代码和数据加载到内存",忽略了内核为管理进程而维护的数据结构,显得过于片面,不易理解。

2 为什么要有进程

从软件角度讲,把你的二进制可执行程序加载到内存的过程,就叫做创造进程

3 怎么办----重点

4 描述进程---PCB

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。

・课本上称之为 PCB(process control block),Linux 操作系统下的 PCB 是:task_struct。
task_struct 是 PCB 的一种。

・在 Linux 中描述进程的结构体叫做 task_struct。

・task_struct 是 Linux 内核的一种数据结构类型,它会被装载到 RAM(内存)里并且包含着进程的信息。


二 task_struct

内容分类

标示符:描述本进程的唯一标示符,用来区别其他进程。

• 状态:任务状态,退出代码,退出信号等。

• 优先级:相对于其他进程的优先级。 • 程序计数器:程序中即将被执行的下一条指令的地址。

• 内存指针:包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针。

• 上下文数据:进程执行时处理器的寄存器中的数据。(休学例子,要加图 CPU、寄存器)

• I/O 状态信息:包括显示的 I/O 请求、分配给进程的 I/O 设备和被进程使用的文件列表。

• 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。

• 其他信息

• 具体详细信息后续会介绍

组织进程

可以在内核源代码⾥找到它。所有运行在系统⾥的进程都以 task_struct 双链表的形式存在内核

⾥。


三 查看进程

我们可以用一个指令来查看进程:ps axj | grep ./[可执行程序]

查看进程的做法:

1 /proc

2 命令

1 /proc

进程的信息可以通过 /proc 系统文件夹查看

如:要获取PID为1的进程信息,你需要查看 /proc/1 这个文件夹。

ls /proc/[PID]

2 PID

PID 是 Process ID(进程标识符) 的缩写,是操作系统给每个正在运行的进程分配的一个唯一数字编号。

可以把 PID 理解成:进程的身份证号

PID可以被操作系统用作:
区分不同的进程
管理进程的运行(暂停、继续、终止等)
记录进程之间的关系(父进程、子进程)

例如:

终止一个进程:kill 1234(Unix/Linux)

查看进程信息:ps -ef | grep 1234

在 Windows 任务管理器中也能看到 PID

注意:PID不是固定的,它是动态分配和回收的

在系统的同一时间点,每个运行的进程都有一个唯一的 PID。
复用机制:当进程退出后,它的 PID 会被内核回收,并可以分配给新创建的进程。内核会从可用的 PID 池中按顺序分配,不会永久占用。

我们在上面图片左部分看到的数字就是PID

我们想要获取PID,可以用getpid()这个系统调用

3 crtl+c

在 Linux/Unix 终端中,它是发送 SIGINT(中断信号,信号编号 2)的快捷键,默认行为是终止当前前台运行的进程。

作用范围:仅对当前终端的前台进程 / 进程组生效,后台运行的进程不受影响

4 当前路径

cwd:current work dir(当前工作路径)

为什么要有当前路径?为了支持进程访问文件时缺省路径的问题。

当前路径就是进程启动时候所处的路径

5 指令

大多数进程信息同样可以使用top和ps这些用户级工具来获取。

如果改变一个进程的当前工作路径,那么它在新建文件的时候,就一定会改变新建文件的位置

我们来写一段循环输出进程ID的代码

chdir:改变当前的工作路径

我们在上述代码中加上一句

此时工作路径就被改变了,也证明了文件建在哪个路径取决于当前进程的工作路径(cwd)

getcwd:获取程序当前工作路径

我们可以通过getcwd判断路径是否改变

ps ajx:显示所有进程信息

里面每一个选项的详细介绍,我们到后面再讲解·

我可以利用这个系统调用,找到指定的进程:

我们发现上面有一列信息的表头叫做TTY,TTY是用来表示该进程是在哪个窗口启动的


四 父进程和子进程

每个进程除了会记录自己的PID,还会记录自己父进程的PID

getppid():得到父进程的PID

我们来写一个程序看一下:

运行之后发现,父进程的PID不会改变

那么此时的这个父进程是谁?

命令行启动的所有进程,父进程都是bash

bash是一个命令行解释器,它本身也是一个进程!

每一次登录,西铜都会自动提供bash,来进行命令行服务

我们运行bash之后发现,bash本身是一个代码内部具有死循环的软件

当我们用ps去看bash时,发现有些前面带'-',有些不带,为什么呢?

当你每一次远程登录Linux系统时,xshell都会分配一个新窗口,这种远程登录形成的bash,叫做-bash 而手动形成的bash前面没有-

kill-9 PID

杀掉一个进程

bash是如何创造子进程的?

我们先来引入一个新的系统调用:fork 创造一个子进程

使用一下fork:

运行得到:

我们发现fork会分成父进程和子进程分别执行一遍

我们来看一下fork的返回值 是什么:

也就是说,如果成功的话,会把子进程的PID返回给父进程,返回0给子进程

我们来写一个程序测试一下:

运行之后发现:为什么父进程和子进程都运行了?fork怎么能既大于0,又等于0呢?

我们以前学习的代码,不可能两个死循环同时在跑,以前的代码都叫做单循环分支。但是我们现在有了父子两个进程,所有同时存在两个死循环

我们用ps查看一下这两进程,发现这两个进程同时都在运行

所以,我们可以通过fork,让同一份代码,做不同的事情

父进程是如何创建子进程的?

创建子进程:内存中就多了一个进程, 操作系统中多了PCB。子进程会以父进程为模板, 一般会把父进程的结构与变量,都拷贝一份给子进程。但是子进程中也有自己特有的部分:自己独立的PID,PPID等。所以拷贝到子进程中后,会对子进程中的个别属性作出修改

当用fork创建一个子进程时,没有把的数据和代码重新加载的过程。所以此时的拷贝,是浅拷贝 子进程也会指向伏见城的代码和数据,他们共享代码。 但是 子进程只能执行fork之后的代码

fork的三个问题

问题1

子进程只能有一个父进程

返回0:告诉子进程你已经被创建

返回PID:为了告诉父进程多了一个子进程,让它记住子进程的pid,让 父进程通过PID控制子进程

问题2

fork既是一个系统调用,也是一个函数。只要是函数,就有代码块,就有子过程

调用函数时,是需要进入函数内部。fork准备return时,子进程已经创建好了,此时fork内部有夫,子两个进程,也已经被操作系统管理起来了。

return是语句,此时父进程和子进程都需要return(return的代码被共享),各自return一次,返回两次

问题3

对问题3的回答这里只做原理性说明,因为目前的知识没有办法解释完全,所以后面还会针对这部分讲解

进程具有很强的独立性---任何一个进程的奔溃都不会影响另一个进程

问题:代码共享时,数据是怎么处理的?

我们来写一段代码来检验这个问题:

但是我们运行了之后发现:父进程的flag居然不受影响!!

这说明父子进程的数据是分开的

但是,一个变量怎么能有两个值?

我们分别在父进程和子进程中取地址,看一下是否是一个变量

我们发现,地址是一样的,说明是一个变量。那这就说明,这个地址一定不是物理地址!!那是什么地址呢??

我们先引出概念**:这个地址是虚拟地址(具体会在后面的程序地址空间讲解)**

子进程继承父进程的虚拟内存空间,如果不修改数据,打印出来的地址一样。但是如果数据修改,系统会在物理内存中拷贝一个flag,这个拷贝就叫做写时拷贝。此时子进程会通过虚拟内存机制,映射到这个新的flag

这个过程是操作系统自己完成的,不需要手动完成

具体的我们后面讲解

如何利用fork建立多进程?

创建十个进程

注意:.cc后缀却表示c++

相关推荐
郝学胜-神的一滴3 小时前
Linux Socket模型创建流程详解
linux·服务器·开发语言·网络·c++·程序人生
天才奇男子3 小时前
《深度解析HAProxy七层代理:原理、配置与最佳实践》
linux·运维·微服务·云原生
Morantkk3 小时前
股票复盘11.20-11.27
服务器
交换机路由器测试之路3 小时前
交换机专题:什么是ALS(激光器自动关断)
运维·网络·以太网·交换机·节能
学嵌入式的小杨同学3 小时前
【Linux 封神之路】文件操作 + 时间编程实战:从缓冲区到时间格式化全解析
linux·c语言·开发语言·前端·数据库·算法·ux
wifi chicken3 小时前
Linux wlan 之sniffer log 解密详解
linux·wlan·sniffer log·空口包·空口解密
济6173 小时前
ARM Linux 驱动开发篇----字符设备驱动开发(1)--字符设备驱动简介---- Ubuntu20.04
linux·嵌入式硬件
浪客灿心4 小时前
Linux的Ext系列文件系统
linux·运维·服务器·c语言
速易达网络4 小时前
linux命令大全
linux·运维·excel