Win7系统之家 网站地图| TAG标签| RSS订阅| 加入收藏

Linux进程的有关常识介绍

  • 浏览:
  • |
  • 更新:

对于Linux系统管理员来讲,对Linux进程的有关常识需要有肯定的认知,进程和线程比较容易被混淆,只有充分知道了Linux进程才不会弄错,下面记者就给大伙详细介绍下Linux进程吧。

计算机事实上可以做的事情实质上很简单,譬如计算两个数的和,再譬如在内存中探寻到某个地址等等。这类最基础的计算机动作被叫做指令 (instruction)。所谓的程序(program),就是如此一系列指令的所构成的集合。通过程序,大家可以让计算机完成复杂的操作。程序大部分时候被存储为可实行的文件。如此一个可实行文件就像是一个食谱,计算机可以根据食谱作出可口的饭菜。

那样,程序和进程(process)有什么区别又是什么呢?

进程是程序的一个具体达成。只有菜谱没什么用,大家总要根据菜谱的指点真的一步步实行,才能做出菜肴。进程是实行程序的过程,像根据菜谱,真的去做菜的过程。同一个程序可以实行多次,每次都可以在内存中开辟独立的空间来装载,从而产生多个进程。不一样的进程还可以拥有各自独立的IO接口。

操作系统的一个要紧功能就是为进程提供便捷,譬如说为进程分配内存空间,管理进程的有关信息等等,就仿佛是为大家筹备好了一个精美的厨房。

看一眼进程

第一,大家可以用$ps命令来查看正在运行的进程,譬如$ps -eo pid,comm,cmd,下图为实行结果:

(-e表示列出全部进程,-o pid,comm,cmd表示大家需要PID,COMMAND,CMD信息)

每一行代表了一个进程。每一行又分为三列。第一列PID(process IDentity)是一个整数,每个进程都有一个唯一的PID来代表我们的身份,进程也可以参考PID来辨别其他的进程。第二列COMMAND是这个进程的简称。第三列CMD是进程所对应的程序与运行时所带的参数。

(第三列有一些由中括号[]括起来的。它们是kernel的一部分功能,被打扮成进程的样子以便捷操作系统管理。大家不必考虑它们。)

大家看第一行,PID为1,名字为init。这个进程是实行/bin/init这一文件(程序)生成的。当Linux启动的时候,init是系统创建的第一个进程,这一进程会一直存在,直到大家关闭计算机。这一进程有特殊的重要程度,大家会不断提到它。

怎么样创建一个进程

事实上,当计算机开机的时候,内核(kernel)只打造了一个init进程。Linux kernel并不提供直接打造新进程的系统调用。剩下的所有进程都是init进程通过fork机制打造的。新的进程要通过老的进程复制自己得到,这就是fork。fork是一个系统调用。进程存活于内存中。每一个进程都在内存中分配有是我们的一片空间 (address space)。当进程fork的时候,Linux在内存中开辟出一片新的内存空间给新的进程,并将老的进程空间中的内容复制到新的空间中,此后两个进程同时运行。

老进程成为新进程的父进程(parent process),而相应的,新进程就是老的进程的子进程(child process)。一个进程除去有一个PID以外,还会有一个PPID(parent PID)来存储的父进程PID。假如大家循着PPID不断向上追溯的话,总会发现其源头是init进程。所以说,所有些进程也构成一个以init为根的树状结构。

如下,大家查看目前shell下的进程:

代码如下:

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

PID PPID CMD

16935 3101 sudo -i

16939 16935 -bash

23774 16939 ps -o pid,ppid,cmd

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

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

代码如下:

init─┬─NetworkManager─┬─dhclient

│ └─2*[{NetworkManager}]

├─accounts-daemon───{accounts-daemon}

├─acpid

├─apache2─┬─apache2

│ └─2*[apache2───26*[{apache2}]]

├─at-spi-bus-laun───2*[{at-spi-bus-laun}]

├─atd

├─avahi-daemon───avahi-daemon

├─bluetoothd

├─colord───2*[{colord}]

├─console-kit-dae───64*[{console-kit-dae}]

├─cron

├─cupsd───2*[dbus]

├─2*[dbus-daemon]

├─dbus-launch

├─dconf-service───2*[{dconf-service}]

├─dropbox───15*[{dropbox}]

├─firefox───27*[{firefox}]

├─gconfd-2

├─geoclue-master

├─6*[getty]

├─gnome-keyring-d───7*[{gnome-keyring-d}]

├─gnome-terminal─┬─bash

│ ├─bash───pstree

│ ├─gnome-pty-helpe

│ ├─sh───R───{R}

│ └─3*[{gnome-terminal}]

fork一般作为一个函数被调用。这个函数会有两次返回,将子进程的PID返回给父进程,0返回给子进程。事实上,子进程总可以查看我们的PPID来了解我们的父进程是哪个,如此,一对父进程和子进程就能随时查看他们。

一般在调用fork函数之后,程序会设计一个if选择结构。当PID等于0时,说明该进程为子进程,那样让它实行某些指令,譬如说用exec库函数(library function)读取另一个程序文件,并在目前的进程空间实行 (这事实上是大家用fork的一大目的: 为某一程序创建进程);而当PID为一个正整数时,说明为父进程,则实行另外一些指令。由此,就能在子进程打造之后,让它实行与父进程不一样的功能。

子进程的终结(termination)

当子进程终结时,它会公告父进程,并清空自己所占据的内存,并在kernel里留下我们的退出信息(exit code,假如顺利运行,为0;假如有错误或异常情况,为》0的整数)。在这个信息里,会讲解该进程为何退出。父进程在得知子进程终结时,有责任对该子进程用wait系统调用。这个wait函数能从kernel中取出子进程的退出信息,并清空该信息在kernel中所占据的空间。但,假如父进程早于子进程终结,子进程就会成为一个孤儿(orphand)进程。孤儿进程会被过继给init进程,init进程也就成了该进程的父进程。init进程负责该子进程终结时调用wait函数。

当然,一个糟糕的程序也完全可能导致子进程的退出信息滞留在kernel中的情况(父进程不对子进程调用wait函数),这种情况下,子进程成为僵尸(zombie)进程。当很多僵尸进程积累时,内存空间会被挤占。

进程与线程(thread)

尽管在UNIX中,进程与线程是有联系但不一样的两个东西,但在Linux中,线程只不过一种特殊的进程。多个线程之间可以共享内存空间和IO接口。所以,进程是Linux程序的唯一的达成方法。

总结

程序,进程,PID,内存空间

子进程,父进程,PPID,fork, wait

上面就是Linux进程的有关常识介绍了,通过本文的阅读,相信你对Linux进程有了更深入了知道,管理Linux进程也愈加容易。