linux 进程详解,总结进程操作的相关命令linux,Linux进程基础教程详解

linux 进程详解,总结进程操作的相关命令linux,Linux进程基础教程详解

本文主要详细介绍了Linux的基本过程,具有一定的参考价值。感兴趣的朋友可以参考一下。

计算机实际能做的事情其实很简单,比如计算两个数的和,在内存中找地址等等。这些基本的计算机动作被称为指令。所谓程序就是这样一系列指令的集合。通过程序,我们可以让计算机完成复杂的运算。大多数时候,程序是作为可执行文件存储的。这样的可执行文件就像一个菜谱,电脑可以根据菜谱做出美味的饭菜。

所以,程序和进程(process)的区别又是什么呢?

流程是程序的具体实现。只有当菜谱没有用的时候,我们总是要按照菜谱的指示一步一步的去做菜。Process就是执行程序的过程,类似于按照菜谱实际烹饪的过程。同一个程序可以执行多次,每次都可以加载到内存中一个独立的空间,产生多个进程。不同的进程也可以有自己独立的IO接口。

操作系统的一个重要作用就是为进程提供便利,比如为进程分配内存空间,管理进程的相关信息等。这就像为我们准备了一个漂亮的厨房。

看一眼进程

首先,我们可以使用$ps命令查询正在运行的进程,比如$ps -eo pid,comm,cmd。下图显示了执行结果:

(-e表示列出所有进程,-o pid,comm,cmd表示我们需要pid,COMMAND,CMD信息)

每一行代表一个过程。每行分为三列。第一列PID(进程标识)是一个整数,每个进程都有一个唯一的PID来表示自己的标识。进程也可以根据PID识别其他进程。第二列命令是这个过程的缩写。第三列CMD是对应于运行时的过程和参数的程序。

(第三列有一些用括号[]括起来。它们是内核功能的一部分,被装扮成便于操作系统管理的进程。我们不必去想它们。)

让我们看看第一行。PID为1,名称为init。这个过程是通过执行文件/bin/init生成的。Linux启动时,init是系统创建的第一个进程,这个进程会一直存在,直到我们关闭电脑。这个过程特别重要,我们会一直提到。

如何创建一个进程

实际上,当计算机启动时,内核只建立一个init进程。Linux内核不提供直接建立新进程的系统调用。所有剩余的进程都是由init进程通过fork机制建立的。新的进程是通过从旧的进程中复制自身而获得的,这被称为fork。Fork是一个系统调用。这个过程存在于内存中。每个进程在内存中分配自己的地址空间。当进程分叉时,Linux在内存中为新进程开辟一个新的内存空间,并将旧进程空间的内容复制到新空间。之后,两个进程同时运行。

旧进程成为新进程的父进程,相应地,新进程是旧进程的子进程。除了PID之外,一个进程还将有一个PPID(父PID)来存储父进程的PID。如果我们继续追溯PPID,我们总会发现它的源头是init进程。因此,所有进程也形成了以init为根的树形结构。

如下,我们查询当前shell下的流程:

root@vamei:~# ps -o pid,ppid,cmd

PID PPID CMD

16935 3101须道一号

16939 16935-巴什

23774 16939 ps -o pid、ppid、cmd

我们可以看到第二个进程bash是第一个进程sudo的子进程,而第三个进程ps是第二个进程的子进程。

您还可以使用pstree命令来显示整个进程树:

initnetworkmanagerdhclient

2*[{NetworkManager}]

accounts-daemon{accounts-daemon}

acpid

apache2apache2

2*[apache226*[{apache2}]]

at-spi-bus-laun2*[{at-spi-bus-laun}]

atd

avahi-daemonavahi-daemon

bluetoothd

colord2*[{colord}]

console-kit-dae64*[{console-kit-dae}]

cron

cupsd2*[dbus]

2*[dbus-daemon]

dbus-launch

dconf-service2*[{dconf-service}]

dropbox15*[{dropbox}]

firefox27*[{firefox}]

gconfd-2

geoclue-master

6*[getty]

gnome-keyring-d7*[{gnome-keyring-d}]

gnome-terminalbash

bashpstree

gnome-pty-helpe

shR{R}

3*[{gnome-terminal}]

Fork通常作为函数调用。这个函数将返回两次,将子进程的PID返回给父进程,将0返回给子进程。实际上,子进程可以随时查询它的PPID来知道它的父进程是谁,这样一对父进程和子进程就可以随时相互查询。

通常调用fork函数后,程序会设计一个if选择结构。当PID等于0时,说明进程是子进程,那么让它执行一些指令,比如用exec库函数读取另一个程序文件,在当前进程空间执行(这其实是使用fork的一个很大的目的:为某个程序创建一个进程);PID为正整数时,表示是父进程,其他指令会被执行。因此,在建立子进程后,它可以执行与父进程不同的功能。

子进程的终结(termination)

子进程终止时,会通知父进程,清空其占用的内存,并在内核中留下自己的退出信息(退出代码,如果运行顺利,为0;如果有错误或异常情况,则为0的整数)。在此消息中,它将解释进程退出的原因。当父进程知道子进程结束时,它负责在子进程上使用等待系统调用。这个wait函数可以从内核中取出子进程的退出信息,并清除这些信息在内核中占用的空间。但是,如果父进程在子进程之前结束,子进程将成为孤儿进程。孤儿进程将被init进程采用,init进程将成为该进程的父进程。当子进程终止时,init进程负责调用wait函数。

当然,一个坏的程序也可能导致子进程的退出信息滞留在内核中(父进程不调用子进程的wait函数)。在这种情况下,子进程就变成了僵尸进程。当僵尸进程大量积累时,内存空间就会被挤压。

进程与线程(thread)

虽然在UNIX中,进程和线程是两个相关但不同的东西,但在Linux中,线程只是一个特殊的进程。多个线程可以共享内存空间和IO接口。因此,进程是实现Linux程序的唯一途径。

总结

程序、进程、PID、存储空间

子进程、父进程、PPID、分叉、等待

这就是本文的全部内容。希望对大家的学习有帮助,支持我们。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: