【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++

相关推荐
寂柒20 小时前
信号量——基于环形队列的生产消费模型
linux·ubuntu
一袋米扛几楼9821 小时前
【密码学】CrypTool2 工具是什么?
服务器·网络·密码学
vin_zheng1 天前
破解企业安全软件网络拦截实战记录
运维
林姜泽樾1 天前
Linux入门第十二章,创建用户、用户组、主组附加组等相关知识详解
linux·运维·服务器·centos
xiaokangzhe1 天前
Linux系统安全
linux·运维·系统安全
feng一样的男子1 天前
NFS 扩展属性 (xattr) 提示操作不支持解决方案
linux·go
南棱笑笑生1 天前
20260310在瑞芯微原厂RK3576的Android14查看系统休眠时间
服务器·网络·数据库·rockchip
xiaokangzhe1 天前
Nginx核心功能
运维·nginx
松果1771 天前
以本地时钟为源的时间服务器
运维·chrony·时间服务器
XDHCOM1 天前
ORA-32152报错咋整啊,数据库操作遇到null number问题远程帮忙修复
服务器·数据库·oracle