【计算机系统基石与Linux进程管理深度解析】(一):https://developer.aliyun.com/article/1425708
3.进程
3.1.基本概念
- 课本概念:程序的一个执行实例,正在执行的程序,加载到内存中的程序等
- 内核观点:担当分配系统资源(CPU时间,内存)的实体。
3.2.描述进程-PCB
- 进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
- 课本上称之为PCB(process control block),PCB通常被实现为一种数据结构,而在C或C++等编程语言中,这个数据结构通常被定义为struct(结构体)或class(类)。
- Linux操作系统下的PCB是: task_struct
为什么程序加载到内存,变成进程之后,我们要给每一个进程形成一个PCB对象呢?
因为操作系统不认识这些以.exe的可执行文件,操作系统需要管理(先描述,再组织),PCB(Process Control Block,进程控制块)用于描述和维护进程的各种信息。当程序加载到内存并成为一个进程时,操作系统需要管理和跟踪这些进程。PCB 是操作系统用来管理进程的数据结构,它包含了关于进程的各种重要信息,如进程状态、程序计数器(PC)、内存分配情况、寄存器的值、进程优先级、进程ID等等。
进程的新定义 = 内核PCB对象 (内核数据结构)+ .exe可执行程序
未来,所有对进程的控制和操作,都只和进程的PCB有关,和进程的可执行程序没有关系!!!
PCB相当于节点(Node),可以放到任意数据结构中。
task_struct-PCB的一种
- 在Linux中描述进程的结构体叫做task_struct。
- task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。
task_ struct内容分类 - 操作系统内部的数据 - 系统调用
- 标示符: 描述本进程的唯一标示符,用来区别其他进程。
- 状态: 任务状态,退出代码,退出信号等。
- 优先级: 相对于其他进程的优先级。
- 程序计数器: 程序中即将被执行的下一条指令的地址。
- 内存指针: 包括程序代码和进程相关数据的指针,还有和其他进程共享的内存块的指针
- 上下文数据: 进程执行时处理器的寄存器中的数据[休学例子,要加图CPU,寄存器]。
- I/O状态信息: 包括显示的I/O请求,分配给进程的I/O设备和被进程使用的文件列表。
- 记账信息: 可能包括处理器时间总和,使用的时钟数总和,时间限制,记账号等。
- 其他信息
程序计数器:
3.3.组织进程
可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里。
3.4.查看进程
ps axj
是一个用于在Unix/Linux系统上显示当前运行进程信息的命令。
下面是对该命令各部分的解释:
ps
:显示进程信息的命令。a
:选择在终端上运行的所有进程,但不包括其他用户的进程。x
:选择没有控制终端的进程,包括后台进程和其他用户启动的进程。j
:以BSD风格的进程列表格式显示额外的信息,包括进程组ID、会话ID和控制终端。
运行 ps axj
会以表格形式输出各种列,提供有关正在运行的进程的信息。具体的列可能包括:
- PID(进程ID): 进程的唯一标识符。
- PGID(进程组ID): 进程所属的进程组的ID。
- SID(会话ID): 进程所属的会话的ID。
- TTY(控制终端): 与进程关联的终端。
- TIME(CPU时间): 进程累积使用的CPU时间。
- COMMAND(命令): 启动进程的命令及其参数。
然后我们来写一个代码,这个代码是一个死循环的输出"I am a process!",然后运行我们的程序。
一旦我们将程序运行起来,此时可执行程序立马就变成了进程。怎么证明呢?
我们发现第一个是我们的代码进程,那第二个是什么呢?第二个也是一个进程,grep在过滤的时候,它自己也是一个程序,当它过滤的时候,它的过滤关键字是包含myprocess的,一瞬间grep也变成了进程,因为包含了myprocess,所以也被留下来了。结论:几乎所有的独立的指令,就是程序,它运行起来,也要变成进程。如果我们不想要的话,可以后面加上:grep -v grep
grep -v grep 是在Unix/Linux环境中经常用于过滤命令输出的一种方式,用于排除包含字符串 "grep" 的行。让我们分解一下这个命令的各部分:
grep
:这是一个用于在文本数据集中搜索匹配正则表达式的命令行实用程序。-v
:这个选项反转匹配,也就是说,它选择所有不匹配指定模式的行。grep
:第二个 "grep" 是要从输出中排除的模式。在这种情况下,你排除包含单词 "grep" 的行。
因此,当你使用 grep -v grep
时,实际上是在说“显示所有不包含单词 'grep' 的行”。这通常用于在查看进程或服务输出时,排除实际的 grep
命令本身。
我们可以通过循环测试间隔1秒来查看当前进程,进程是有生命的!!!
task_ struct内容分类 - 操作系统内部的数据 - 系统调用
因此我们来修改一下我们的程序
然后我们编译运行一下:
一般在我们的Linux中,普通进程都会有他的父进程!!!怎么获取呢?调用getppid()。
此时我们就可以看到相关父进程的pid。
我们再多次运行我们的程序,我们发现进程的pid一直在变化,而父进程的pid始终没有变化。
当一个程序多次运行时,它的进程PID会不断变化,因为每次运行都会创建一个新的进程。每个进程都有一个唯一的PID,它是操作系统为了标识和管理进程而分配的数字标识符。然而,父进程的PID通常不会改变,因为它是启动新进程的原始进程的标识符。子进程会继承父进程的一些属性,包括父进程的PID。所以,无论我们运行多少次程序,它们的父进程的PID通常会保持不变,因为它们都是由同一个父进程启动的。
如果你在多次运行中看到父进程的 PID 一直没有变化,这表明每次运行的新进程都是由同一个父进程启动的,我们可以看到父进程是bash,是我们的命令行接收器,在命令行执行的指令或者程序都是bash的子进程。这里的bash就是曾经提到的王婆,而子进程就是实习生。
进程的信息可以通过 /proc 系统文件夹查看
LInux会把进程相关的数据以文件的形式显示到系统文件中。
以数字进行命名的我们称之为目录,这个数字就是我们进程的PID。如果我们运行我们的程序,那我们是否可以在这个系统/proc目录下查看到我们的此时进程的一个目录。
同时我们还可以看到这个进程的具体信息:ls /proc/19132 -l
我们着重看一下上面标记的两个。
"exe" 是 "可执行文件"(Executable)的缩写。它是一种计算机文件格式,通常用于存储程序代码,在LInux下可以通过在磁盘中的绝对路径进行运行,上面exe指向的就是可执行程序在磁盘中的绝对路径。
如果我们将这个可执行程序删掉呢?已经运行的进程还在吗?
删除一个可执行程序文件不会影响已经在运行的进程。当你运行一个可执行程序时,操作系统会将该磁盘中存在的这个程序的拷贝加载到内存中,然后执行。一旦程序开始执行,它与原始的可执行文件就没有直接的关系了。
删除可执行文件后,文件系统上的相应实体被删除,但已经加载到内存中的程序仍在执行。这是因为在执行过程中,程序已经被加载到系统内存中,而不再依赖于原始文件。程序会一直执行,直到其运行结束或被手动终止。
如果你删除了一个正在运行的可执行文件,该文件的文件名和路径信息将不再可见,但操作系统仍会保留该程序在内存中的拷贝。只有当该程序运行结束并释放了系统资源,或者被手动终止时,相关的进程才会被终止。
"cwd" 是 "Current Working Directory" 的缩写,表示当前工作目录。在操作系统中,当前工作目录是指在命令行或程序中正在进行操作的目录路径。
当你在命令行中运行命令或执行程序时,操作系统会将这些操作基于当前工作目录来进行,比如创建一个文件。
终端或命令行提示通常显示当前工作目录的路径。当我们执行上面的可执行程序后,文件就在当前工作目录显示了,同时还可以通过绝对路径寻找到这个文件。
如果我们想改变不当前工作目录呢?系统调用接口为我们提供了一个函数:chdir
然后我们来修改一下我们的代码
然后执行我们的代码,我们发现当前工作目录发生改变了,同时创立的文件绝对路径也发生变化
【计算机系统基石与Linux进程管理深度解析】(三):https://developer.aliyun.com/article/1425715