javamac系统通过pid获取进程名称_操作系统 - 对进程的操作

在大多数系统中进程都可以并发的执行,并且他们可以动态地创建和结束。因此,这些系统必须提供进程创建和结束的机制。

进程创建

在执行的过程中,一个进程可能会创建几个新的进程。创建进程的进程叫做父进程,新的进程称为该进程的子进程。这些进程中的每一个也可以创建其他的进程,这就形成了一个进程树。

大多数的操作系统(包括UNIX,Linux和Windows)根据独一无二的进程标识符process identifile(pid)来识别进程。pid为在系统中的每个进程提供了一个独一无二的数值,它可以被用过访问内核中单个进程各种属性的索引。

下图展示了Linux操作系统中一个典型的进程树。展示了每个进程的名字和其pid。进程systmed作为所有用户进程根进程和父进程,并且是系统引导时的第一个被创建的用户进程。当系统被引导完后,systemd进程会创建提供额外服务的诸如,网页、打印、ssh等等的进程。下图中没我们看到systemd有两个子进程,logind和sshd。logind是负责管理直接登入到系统的客户端的进程。在这个示例中,客户端通过使用bash shell登入并且分配pid8416。通过使用bash命令行接口,这个用户已经创建了ps和vim编辑器这两个进程。sshd是负责管理客户端通过ssh(secure shell)连接到系统的进程。

aa8365b2ad3bb76a608b44c792675e04.png

init 和 systemd进程

传统的UNIX系统把init进程作为所有子进程的根进程。init,也被称为System V init, 被分配给一个值为1的pid,并且是当系统引导完后第一个被创建的进程。

Linux系统一开始也是采用了System V init这种方法,但最近的分发版已经用systemd取代了init。systemd作为系统的初始化进程,很像System V init,但更灵活,并且别init提供了更多的服务。

在UNIX和Linux系统上,我们可以用ps命令获取进程的列表,如下:

a8717cc4ada6963bb3b76f7f9d839c9f.png

这会罗列系统中当前所有活动的进程的信息。一个进程树可以通过递归追踪父进程的方式直到systemd为止的方式来构建。此外,Linxu提供了pstree命令,这里展示系统中所有进程的树结构。如下所示:

80fe0643c799162d02e3a135e862875d.png

一般来说,当一个进程创建子进程时,子进程会需要某些资源(CPU事件,内存,文件,I/O设备)来完成它的任务。一个子进程可以从操作系统直接获取资源,或者可以被限制为父进程资源的一个子集。父进程可以把资源分片给子进程,或者也可以在子进程间共享资源(比如共享内存或文件)。将子进程限制为父级资源的子集可防止任何进程通过创建太多子进程而使系统超载。

除了提供各种物理和逻辑上的资源,父进程也可以传递初始化数据给子进程。比方说,如果一个进程的功能是展示文件的内容在屏幕或终端上,比如说hw1.c。当进程被创建时,它会从父进程那里得到hw1.c文件的名字作为输入。通过使用这个名字,它会打开文件,并把其中的内容打印出来。它也可以获取输出设备的名字。作为选择,一些操作系统也可以把资源传递给子进程处理。在这样的系统中,新的进程会得到两打开的文件,hw1.c和终端设备,从而在两者之间做简单的传递。

当一个进程创建一个新的进程时,会存在两种可能性:

  • 父进程与子进程并行工作
  • 父进程等待,直到一些或所有的子进程结束工作。

对于新的进程也有两种地址空间的可能性:

  • 子进程拷贝父进程的地址空间(有与父进程一样的程序和数据)
  • 子进程装载了一个新的程序

为了演示这两种不同,这里首先考虑Linux操作系统。在Linux中,正如我们已经看到的,每个进程都有一个pid,这是一个独一无二的整数。一个新的进程可以通过fork()系统调用创建。新的进程由原进程地址空间里的拷贝组成。这个机制可以让父进程与子进程做简单的通信。两个进程(父进程和子进程)可以在fork()后继续执行,不同的是,对于子进程来说,fork返回的是0,而对于父进程来说,返回的是子进程的pid(非零)。

在fork()系统调用之后,两个进程中的一个一般会执行exec()系统调用,用新的程序来取代进程内存空间中的内容。exec系统调用会把二进制文件加载进内存,然后开始执行。按照这种方式,两个进程可以通信并且独立运行。然后父进程可以创建更多新的子进程,或者,如果没有什么其他需要做的,就可调用wait()系统调用,把它自己从ready queue中移除,直到子进程结束运行。因为exec调用会用新程序覆盖进程的地址空间。所以exec不会返回控制权,除非有错误发生。

下图展示了上述描述的Linux系统调用的C语言程序。

8e7e305a62700324360946a40c96f8a6.png

现在我们有了两个完全不同的进程运行着相同的程序。唯一的不同是对于子进程来说,pid的值为零,而对于父进程来说pid是一个大于零的数(实际上,这就是子进程的pid)。子进程从父进程那里继承了权限和调度属性,以及某些资源,比如说打开的文件。子进程随后使用execlp()系统调用用/bin/ls Linux命令覆盖它的地址空间。父进程则使用wait()系统调用来等待子进程的完成。当子进程完成后,父进程从wait()调用中恢复过来,然后整个结束进程。如下图所示:

87015d0586374faf7756c9e40acfcadf.png

当然,没有什么可以阻止子进程不调用exec()而是继续作为父进程的副本执行的。在这种情况下,父进程和子进程是运行相同代码指令的并发进程。由于子进程是父进程的副本,因此每个进程都有其自己的所有数据副本。

进程结束

进程在完成执行其最终语句时终止,并要求操作系统使用exit()系统调用将其删除。那时,进程可以将状态值(通常是整数)返回到其等待的父进程(通过wait()系统调用)。进程的所有资源(包括物理和虚拟内存,打开的文件和I / O缓冲区)由操作系统释放并回收。

终止也可能在其他情况下发生。一个进程可以通过适当的系统调用(例如,Windows中的TerminateProcess())导致另一个进程的终止。通常,此类系统调用只能由要终止的进程的父进程调用。否则,用户-或行为不当的应用程序-可能会任意杀死另一个用户的进程。请注意,如果要终止子进程,父进程需要知道其子进程的PID。因此,当一个进程创建一个新进程时,新创建的进程的pid将传递给父进程。

父进程可以出于多种原因终止其子进程之一的执行,例如:

  • 子进程已超出其分配的某些资源的使用量。(要确定是否已发生这种情况,父进程必须具有检查其子进程状态的机制。)
  • 不再需要分配给子进程的任务。
  • 父进程正在退出,并且如果父进程终止,则操作系统不允许子级继续运行。

如果父进程终止,则某些系统不允许子进程存在。在这样的系统中,如果一个进程终止(正常或异常),那么它的所有子进程也必须终止。这种现象称为级联终止,通常是由操作系统启动的。

为了说明进程的执行和终止,在Linux和UNIX系统中,我们可以通过使用exit()系统调用(以退出状态作为参数)来终止进程:

c453ccaef9cb09693e51c9dd752c1542.png

实际上,在正常终止下,exit()将被直接调用(如上所示)或被间接调用,因为C运行库(添加到Linux可执行文件中)在默认情况下将包括对exit()的调用。

父进程可以通过使用wait()系统调用来等待子进程的终止。向wait()系统调用传递了一个参数,该参数允许父级获取子进程的退出状态。该系统调用还返回终止子进程的进程标识符,以便父进程可以知道哪个子进程已终止:

3bed81440f677d7f2c395da31d53c0d3.png

进程终止时,操作系统将释放其资源。但是,它在进程表中的条目必须保留在那里,直到父进程调用wait()为止,因为进程表包含进程的退出状态。一个已经终止但其父级尚未调用wait()的进程是被称为僵尸zombie进程。当所有进程终止时,所有进程都会转换到此状态,但是通常它们只是短暂地以僵尸形式存在。一旦父级调用wait(),僵尸进程的进程标识符及其在进程表中的条目将被释放。

现在考虑如果父母不调用wait()而是终止,其子进程会保留为孤儿orphans,将会发生什么。传统的UNIX系统通过将init进程作为新的父进程分配给孤立进程解决了这种情况。(init充当UNIX系统中进程层次结构的根。)init会进程定期调用wait(),从而允许收集任何孤儿进程的退出状态并释放孤儿进程的标识符和进程表条目。

尽管大多数Linux系统已将init替换为systemd,但尽管Linux也允许systemd以外的其他进程继承孤儿进程并管理其终止,但systemd仍可以发挥相同的作用。

Android进程层次结构

由于诸如内存有限的资源限制,移动操作系统可能必须终止现有进程以回收有限的系统资源。 Android并不是随意终止进程,而是有一个进程的重要性的层次结构,并且当系统必须终止进程以使资源可用于新的或更重要的进程时,Android会按重要性递增的顺序终止进程。从最重要到最不重要,进程分类的层次结构如下:

- 前台进程 - 屏幕上可见的当前进程,代表用户当前正在与之交互的应用程序

- 可见进程 - 在前台上不直接可见但是是正在执行前台进程所引用的活动的进程(即,一个执行后,其状态会显示在前台进程上的)

- 服务进程 - 与后台进程类似,但正在执行对用户来说显而易见活动的进程(例如流音乐)

- 后台进程 - 可能正在执行活动但对用户不明显的进程。

- 空进程 - 不包含与任何应用程序关联的活动组件的进程。

如果必须回收系统资源,Android将首先终止空进程,然后终止后台进程,依此类推。进程分配了重要性的排名,但Android会尝试为进程分配尽可能高的排名。例如,如果某个进程正在提供服务并且也是可见的,则将为其分配更为重要的可见分类。

此外,Android开发实践建议遵循进程生命周期的准则。遵循这些准则后,进程的状态将在终止之前保存,并且如果用户导航回应用程序,则将以其保存状态恢复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值