一 、進程的概念和分類
1.進程的概念
Linux是一個多用戶多任務的操作系統。多用戶是指多個用戶可以在同一時間使用同一個linux系統;多任務是指在Linux下可以同時執行多個任務,更詳細的說,linux采用了分時管理的方法,所有的任務都放在一個隊列中,操作系統根據每個任務的優先級為每個任務分配合適的時間片,每個時間片很短,用戶根本感覺不到是多個任務在運行,從而使所有的任務共同分享系統資源,因此linux可以在一個任務還未執行完時,暫時掛起此任務,又去執行另一個任務,過一段時間以後再回來處理這個任務,直到這個任務完成,才從任務隊列中去除。這就是多任務的概念。
上面說的是單CPU多任務操作系統的情形,在這種環境下,雖然系統可以運行多個任務,但是在某一個時間點,CPU只能執行一個進程,而在多CPU多任務的操作系統下,由於有多個CPU,所以在某個時間點上,可以有多個進程同時運行。
進程的的基本定義是:在自身的虛擬地址空間運行的一個獨立的程序,從操作系統的角度來看,所有在系統上運行的東西,都可以稱為一個進程。
需要注意的是:程序和進程是有區別的,進程雖然有程序產生,但是它並不是程序,程序是一個進程指令的集合,它可以啟用一個或多個進程,同時,程序只占用磁盤空間,而不占用系統運行資源,而進程僅僅占用系統內存空間,是動態的、可變的,關閉進程,占用的內存資源隨之釋放。
例如,用戶在linux上打開一個文件、就會產生一個打開文件的進程,關閉文件,進程也隨機關閉。如果在系統上啟動一個服務,例如啟動tomcat服務,就會產生一個對應的java的進程。而如果啟動apache服務,就會產生多個httpd進程。
2.進程的分類
按照進程的功能和運行的程序分類,進程可劃分為兩大類:
系統進程:可以執行內存資源分配和進程切換等管理工作;而且,該進程的運行不受用戶的干預,即使是root用戶也不能干預系統進程的運行。
用戶進程:通過執行用戶程序、應用程序或內核之外的系統程序而產生的進程,此類進程可以在用戶的控制下運行或關閉。
針對用戶進程,又可以分為交互進程、批處理進程和守護進程三類。
交互進程:由一個shell終端啟動的進程,在執行過程中,需要與用戶進行交互操作,可以運行於前台,也可以運行在後台。
批處理進程:該進程是一個進程集合,負責按順序啟動其他的進程。
守護進程:守護進程是一直運行的一種進程,經常在linux系統啟動時啟動,在系統關閉時終止。它們獨立於控制終端並且周期性的執行某種任務或等待處理某些發生的事件。例如httpd進程,一直處於運行狀態,等待用戶的訪問。還有經常用的crond進程,這個進程類似與windows的計劃任務,可以周期性的執行用戶設定的某些任務。
3.進程的屬性
(1)進程的幾種狀態
進程在啟動後,不一定馬上開始運行,因而進程存在很多種狀態。
可運行狀態:處於這種狀態的進程,要麼正在運行、要麼正准備運行。
可中斷的等待狀態:這類進程處於阻塞狀態,一旦達到某種條件,就會變為運行態。同時該狀態的進程也會由於接收到信號而被提前喚醒進入到運行態。
不中斷的等待狀態:與“可中斷的等待狀態”含義基本類似,唯一不同的是處於這個狀態的進程對信號不做響應。
僵死狀態:也就是僵死進程,每個進程在結束後都會處於僵死狀態,等待父進程調用進而釋放資源,處於該狀態的進程已經結束,但是它的父進程還沒有釋放其系統資源。
暫停狀態:表明此時的進程暫時停止,來接收某種特殊處理,
(2)進程之間的關系
在linux系統中,進程ID(用PID表示)是區分不同進程的唯一標識,它們的大小是有限制的,最大ID為32768,用UID和GID分別表示啟動這個進程的用戶和用戶組。所有的進程都是PID為1的init進程的後代,內核在系統啟動的最後階段啟動init進程,因而,這個進程是linux下所有進程的父進程,用PPID表示父進程。
下面是通過ps命令輸出的sendmail進程信息:
[root@localhost ~]# ps -ef|grep sendmail
UID PID PPID C STIME TTY TIME CMD
root 3614 1 0 Oct23 ? 00:00:00 sendmail: accepting connections
相對於父進程,就存在子進程,一般每個進程都必須有一個父進程,父進程與子進程之間是管理與被管理的關系,當父進程停止時,子進程也隨之消失,但是子進程關閉,父進程不一定終止。
如果父進程在子進程退出之前就退出,那麼所有子進程就變成的一個孤兒進程,如果沒有相應的處理機制的話,這些孤兒進程就會一直處於僵死狀態,資源無法釋放,此時解決的辦法是在啟動的進程內找一個進程作為這些孤兒進程的父進程,或者直接讓init進程作為它們的父進程,進而釋放孤兒進程占用的資源。
二、 進程的監控與管理
Linux下,監控和管理進程的命令有很多,下面我們以ps、top、pstree、lsof四個最常用的指令介紹如果有效的監控和管理linux下的各種進程。
2.1 利用ps命令監控系統進程
ps是linux下最常用的進程監控命令,關於ps命令的語法和使用選項,我們在第四章已經有了詳細的講解,這裡重點講述如何利用ps指令監控和管理系統進程。
請看下面的示例:
下面是apache進程的輸出信息
[root@localhost ~]#ps -ef | grep httpd
UID PID PPID C STIME TTY TIME CMD
nobody 7272 26037 0 Nov06 ? 00:00:00 /apache2/bin/httpd -k start
nobody 7274 26037 0 Nov06 ? 00:00:00 /apache2/bin/httpd -k start
nobody 7400 26037 0 Nov06 ? 00:00:00 /apache2/bin/httpd -k start
nobody 7508 26037 0 00:09 ? 00:00:00 /apache2/bin/httpd -k start
nobody 7513 26037 0 00:09 ? 00:00:00 /apache2/bin/httpd -k start
nobody 7515 26037 0 00:09 ? 00:00:00 /apache2/bin/httpd -k start
nobody 11998 26037 0 11:14 ? 00:00:00 /apache2/bin/httpd -k start
nobody 12941 26037 0 16:25 ? 00:00:00 /apache2/bin/httpd -k start
nobody 12979 26037 0 16:44 ? 00:00:00 /apache2/bin/httpd -k start
root 26037 1 0 Oct23 ? 00:00:00 /apache2/bin/httpd -k start
其中,UID是用戶的ID標識號,PID是進程的標識號,PPID表示父進程,STIME表示進程的啟動時間,TTY表示進程所屬的終端控制台,TIME表示進程啟動後累計使用的CPU總時間,CMD表示正在執行的命令。
從中可以清楚的看出,父進程和子進程的對應關系, PPID為26037的所有進程均為子進程,而PID為26037的進程是所有子進程的父進程,子進程由nobody用戶啟動,而父進程由root用戶啟動,父進程對應的PPID為1,即父進程同時為init進程的子進程。
其實也可以通過下面的指令方式查看子進程與父進程的對應關系,請看如下操作:
[root@localhost ~]# ps auxf | grep httpd
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 26037 0.0 0.1 6316 2884 ? Ss Oct23 0:00 /apache2/bin/httpd -k start
nobody 7272 0.0 0.1 7016 3740 ? S Nov06 0:00 \_ /apache2/bin/httpd -k start
nobody 7274 0.0 0.1 7016 3704 ? S Nov06 0:00 \_ /apache2/bin/httpd -k start
nobody 7400 0.0 0.1 7012 3676 ? S Nov06 0:00 \_ /apache2/bin/httpd -k start
nobody 7508 0.0 0.1 7012 3732 ? S 00:09 0:00 \_ /apache2/bin/httpd -k start
nobody 7513 0.0 0.1 7012 3700 ? S 00:09 0:00 \_ /apache2/bin/httpd -k start
nobody 12979 0.0 0.1 7016 3684 ? S 16:44 0:00 \_ /apache2/bin/httpd -k start
nobody 12980 0.0 0.1 7012 3652 ? S 16:44 0:00 \_ /apache2/bin/httpd -k start
nobody 12982 0.0 0.1 7016 3664 ? S 16:44 0:00 \_ /apache2/bin/httpd -k start
nobody 22664 0.0 0.1 6880 3540 ? S 22:24 0:00 \_ /apache2/bin/httpd -k start
其中,%CPU表示進程占用的CPU百分比,%MEM表示進程占用內存的百分比,VSZ表示進程虛擬大小,RSS表示進程的實際內存(駐留集)大小(單位是頁)。STAT表示進程的狀態,進程的狀態有很多種:用“R”表示正在運行中的進程,用“S”表示處於休眠狀態的進程,用“Z”表示僵死進程,用“<”表示優先級高的進程,用“N”表示優先級較低的進程,用“s”表示父進程,用“+”表示位於後台的進程。START表示啟動進程的時間。
這個例子將進程之間的關系用樹形結構形象的表示出來,可以很清楚的看到,第一個進程為父進程,而其它進程均為子進程。同時從這個輸出還可以看到每個進程占用CPU、內存的百分比,還有進程所處的狀態等等。
2.2 利用pstree監控系統進程
pstree命令以樹形結構顯示程序和進程之間的關系,使用格式如下:
pstree [-acnpu] [<PID>/<user>]
選項含義如下:
-a 顯示啟動每個進程對應的完整指令,包含啟動進程的路徑、參數等等。
-c 不使用精簡法顯示進程信息,即顯示的進程中包含子進程和父進程。
-n 根據進程PID號來排序輸出,默認是以程序名稱排序輸出的。
-p 顯示進程的PID。
-u 顯示進程對應的用戶名稱。
PID:即進程對應的PID號,或者叫進程識別號。
user:系統用戶名。
pstree清楚的顯示了程序和進程之間的關系,如果不指定進程的PID號,或者不指定用戶名稱,則將以init進程為根進程,顯示系統的所有程序和進程信息,若指定用戶或PID,則將以用戶或PID為根進程,顯示用戶或PID對應的所有程序和進程。
舉例如下:
如果想知道某個用戶下都啟動了哪些進程的話,pstree指令可以很容易實現,下面顯示mysql用戶下對應的進程信息,執行如下命令:
[root@localhost ~]# pstree mysql
mysqld---6*[{mysqld}]
該輸出顯示了mysql用戶下對應的進程為mysqld,並且mysqld進程擁有5個子進程(5個子進程加一個父進程,共6個進程)。
為了更詳細的了解每個進程的信息,例如每個子進程和父進程對應的PID,執行如下命令:
[root@localhost ~]# pstree -c -p mysql
mysqld(18785)-+-{mysqld}(18787)
|-{mysqld}(18788)
|-{mysqld}(18789)
|-{mysqld}(18790)
|-{mysqld}(18791)
`-{mysqld}(29625)
通過“-p、-c”參數,清楚的顯示了父進程和子進程,以及它們各種的PID。
如果知道進程對應的PID,想得到進程是由哪個用戶啟動的,可以執行如下命令:
[root@localhost ~]# pstree -u 26037
httpd---10*[httpd(nobody)]
從上面可知,httpd進程是由nobody用戶啟動的。
如果要查看httpd父進程和每個子進程分別對應的PID,可以執行如下命令組合:
[root@localhost ~]# pstree -u -p 26037
httpd(26037)-+-httpd(24562,nobody)
|-httpd(24563,nobody)
|-httpd(24566,nobody)
|-httpd(24567,nobody)
|-httpd(24631,nobody)
|-httpd(24648,nobody)
|-httpd(24650,nobody)
|-httpd(24654,nobody)
|-httpd(26156,nobody)
`-httpd(29014,nobody)
如果要得到啟動httpd進程的程序路徑、參數組合,執行如下命令:
[root@localhost ~]# pstree -a -u -p 26037
httpd,26037 -k start
|-httpd,24563,nobody -k start
|-httpd,24566,nobody -k start
|-httpd,24567,nobody -k start
|-httpd,24631,nobody -k start
|-httpd,24648,nobody -k start
|-httpd,24650,nobody -k start
|-httpd,24654,nobody -k start
|-httpd,26156,nobody -k start
`-httpd,29014,nobody -k start
2.3 利用top監控系統進程
top命令是監控系統進程必不可少的工具,與ps命令相比,top命令動態、實時的顯示進程狀態,而ps只能顯示進程某一時刻的信息,同時,top命令提供了一個交互界面,用戶可以根據需要,人性化的定制自己的輸出,更清楚的了解進程的實時狀態。
關於top指令的用法,在第四章已經有了詳細的介紹,這裡通過幾個例子,闡述一下top命令在系統進程監控中的作用和優點。
下面這個例子是某系統在某時刻執行top命令後的輸出:
[root@webserver ~]# top
Tasks: 126 total, 1 running, 123 sleeping, 1 stopped, 1 zombie
Cpu(s): 0.8% us, 0.1% sy, 0.0% ni, 99.0% id, 0.0% wa, 0.0% hi, 0.0% si
Mem: 8306544k total, 8200452k used, 106092k free, 234340k buffers
Swap: 8385888k total, 160k used, 8385728k free, 7348560k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
21115 root 23 0 1236m 360m 2384 S 6 4.4 382:24.14 java
30295 root 16 0 3552 984 760 R 1 0.0 0:00.09 top
30118 nobody 15 0 6904 3132 1676 S 0 0.0 0:00.47 httpd
30250 nobody 15 0 6900 3088 1660 S 0 0.0 0:00.06 httpd
1 root 16 0 1780 552 472 S 0 0.0 0:01.25 init
從top命令的輸出可知,此系統有java和httpd兩個用戶進程在運行。
進程PID為21115的java進程由root用戶啟動,優先級(PR)為23,占用的虛擬內存總量(VIRT)為1236M,未被換出的物理內存(RES)為360M,共享內存(SHR)為2384 kb。通過這幾個選項可以了解java進程對內存的使用量,有助於系統管理員對系統虛擬內存使用狀況的掌控。
此刻java進程處於休眠狀態(S),從上次更新到現在java占用cpu時間(%CPU)為6%,占用物理內存(%MEM)為4.4%,從進程啟動到現在java占用cpu總時間(TIME+)為“382:24.14”,單位是1/100秒。通過了解這些信息,可以使系統管理員掌握java進程對系統CPU、物理內存的使用狀況。
兩個httpd進程由nobody用戶啟動,優先級都為15,同時都處於休眠狀態。
除去這兩個進程,還有top進程,也就是我們執行top命令產生的進程,從進程狀態項可知,此進程處於運行狀態,另一個是init進程,即所有系統進程的父進程,對應的PID為1。
當然top的輸出還有很多進程信息,這裡僅僅拿出前幾個進程進行重點講解,理解其它進程的含義基本與這些相同。
2.4 利用lsof監控系統進程與程序
lsof全名list opened files,也就是列舉系統中已經被打開的文件,通過lsof,我們就可以根據文件找到對應的進程信息,也可以根據進程信息找到進程打開的文件。
lsof指令功能強大,這裡介紹“-c,-g,-p,-i”這四個最常用參數的使用。更詳細的介紹請參看man lsof。
lsof filename:顯示使用filename文件的進程。
如果想知道某個特定的文件由哪個進程在使用,可以通過“lsof 文件名”方式得到,例如:
[root@localhost ~]# lsof /var/log/messages
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
syslogd 2027 root 1w REG 8,6 43167 31916 /var/log/messages
從這個輸出可知,/var/log/messages文件是由syslogd進程在使用。
lsof -c abc :顯示abc進程現在打開的文件,例如:
[root@localhost ~]# lsof -c nfs
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
nfsd4 2761 root cwd DIR 8,3 4096 2 /
nfsd4 2761 root rtd DIR 8,3 4096 2 /
nfsd4 2761 root txt unknown /proc/2761/exe
nfsd 2762 root cwd DIR 8,3 4096 2 /
nfsd 2762 root rtd DIR 8,3 4096 2 /
nfsd 2762 root txt unknown /proc/2762/exe
nfsd 2763 root cwd DIR 8,3 4096 2 /
nfsd 2763 root rtd DIR 8,3 4096 2 /
nfsd 2763 root txt unknown /proc/2763/exe
上例顯示了nfs進程打開的文件信息,FD列表示文件描述符,TYPE列顯示文件的類型,SIZE列顯示文件的大小,NODE列顯示本地文件的node碼,NAME列顯示文件的全路徑或掛載點。
lsof -g gid:顯示指定的進程組打開的文件情況,例如:
[root@localhost ~]# lsof -g 3626
COMMAND PID PGID USER FD TYPE DEVICE SIZE NODE NAME
sendmail 3626 3626 smmsp cwd DIR 8,8 4853760 32714 /var/spool/clientmqueue
sendmail 3626 3626 smmsp rtd DIR 8,10 4096 2 /
sendmail 3626 3626 smmsp txt REG 8,9 732356 1152124 /usr/sbin/sendmail.sendmail
sendmail 3626 3626 smmsp mem REG 8,10 106397 1158794 /lib/ld-2.3.4.so
sendmail 3626 3626 smmsp mem REG 8,10 95148 1175044 /lib/libnsl-2.3.4.so
.............省略...............
sendmail 3626 3626 smmsp 3u unix 0xf41e5bc0 9592 socket
sendmail 3626 3626 smmsp 4wW REG 8,8 50 523293 /var/run/sm-client.pid
其中,PGID列表示進程組的ID編號。
上面輸出,顯示了sendmail程序當前打開的所有文件、設備、庫及套接字等。
lsof -p PID:PID是進程號,通過進程號顯示程序打開的所有文件及相關進程,例如,想知道init進程打開了哪些文件的話,可以執行“lsof -p 1”命令,輸出結果如下:
[root@localhost ~]# lsof -p 1
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
init 1 root cwd DIR 8,10 4096 2 /
init 1 root rtd DIR 8,10 4096 2 /
init 1 root txt REG 8,10 32684 897823 /sbin/init
init 1 root mem REG 8,10 56320 2175328 /lib/libselinux.so.1
init 1 root mem REG 8,10 106397 1158794 /lib/ld-2.3.4.so
init 1 root mem REG 8,10 1454462 1161560 /lib/tls/libc-2.3.4.so
init 1 root mem REG 8,10 53736 1158819 /lib/libsepol.so.1
init 1 root 10u FIFO 0,13 966 /dev/initctl
? lsof -i 通過監聽指定的協議、端口、主機等信息,顯示符合條件的進程信息。
使用語法為:
lsof -i [46] [protocol][@hostname][:service|port]
46:4代表IPv4,6代表IPv6。
protocol:傳輸協議,可以是TCP或UDP。
hostname:主機名稱或者IP地址。
service:進程的服務名,例如nfs、ssh、ftp等。
port:系統中服務對應的端口號。例如http服務默認對應80,ssh服務默認對應22等等。
例如:
顯示系統中tcp協議對應的25端口進程信息:
[root@localhost ~]# lsof -i tcp:25
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
sendmail 2252 root 4u IPv4 5874 TCP localhost:smtp (LISTEN)
顯示系統中80端口對應的進程信息:
[root@localhost ~]# lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
httpd 16474 nobody 3u IPv6 7316069 TCP *:http (LISTEN)
httpd 16475 nobody 3u IPv6 7316069 TCP *:http (LISTEN)
httpd 16578 nobody 3u IPv6 7316069 TCP *:http (LISTEN)
顯示本機udp協議對應的53端口開啟的進程信息:
[root@localhost ~]# lsof -i [email protected]:53
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
named 21322 named 20u IPv4 9130640 UDP localhost:domain
通過lsof命令能夠清楚的了解進程和文件以及程序之間的對應關系,熟練掌握lsof的使用,對linux的進程管理有很大幫助。
本文出自 “技術成就夢想” 博客,請務必保留此出處http://ixdba.blog.51cto.com/2895551/543737