1. 進程是什麼 定義: 進程是一個具有獨立功能的程序關於某個數據集合的一次可以並發執行的運行活動,是處於活動狀態的計算機程序。 進程作為構成系統的基本細胞,不僅是系統內部獨立運行的實體,而且是獨立競爭資源的基本實體。 進程既然是運行中的程序,則必定有它的開始和結束。對於Linux系統來說,新進程由fork()與execve()等系統調用開始,然後執行,知道它們下達exit()系統調用為止。在這裡,fork()、execve()、exit()都是linux提供給C語言的控制進程的接口。 進程之間的切換:CPU在一個時間點只能處理一個進程,多個進程時,CPU的做法是先用極短的時間處理一個進程,然後將這個進程擱置,將CPU的資源讓給其他進程執行。這個極短的時間稱為時間片。時間片很短(通常只有幾微秒),並且切換很迅速。 關於時間片的調度,在操作系統內核中,有個模塊稱之為調度器(scheduler),它負責管理進程的執行和切換。調度算法會根據進程的優先級決定哪個進程去執行。Linux的進程都有優先級,nice和renice命令可以調整進程的優先級。
2.進程的分類 按照進程的功能和運行的程序分類,進程可劃分為兩大類: - 系統進程:可以執行內存資源分配和進程切換等管理工作;而且,此類進程的運行不受用戶的干預,即使是root用戶也不能干預系統進程的運行。 - 用戶進程:通過執行用戶程序、應用程序或內核之外的系統程序而產生的進程,此類進程可以在用戶的控制下運行或關閉。 針對用戶進程,又可以分為交互進程、批處理進程和守護進程三類。 - 交互進程:由一個shell終端啟動的進程,在執行過程中,需要與用戶進行交互操作,可以運行於前台,也可以運行在後台。 - 批處理進程:該進程是一個進程集合,負責按順序啟動其他的進程。 - 守護進程:守護進程是一直運行的一種進程,經常在linux系統啟動時啟動,在系統關閉時終止。它們獨立於控制終端並且周期性的執行某種任務或等待處理某些發生的事件。例如httpd進程,一直處於運行狀態,等待用戶的訪問。還有經常用的crond進程,這個進程類似與windows的計劃任務,可以周期性的執行用戶設定的某些任務。
3. 創建進程 fork()函數是Linux下產生新進程的系統調用,fork意即“分叉”,用來描述: 一個進程在運行中,如果使用了fork()函數,就產生了另一個進程,於是進程就“分叉”了。 本系統調用產生一個新的進程,叫子進程,調用進程叫父進。 4. 查看進程 在Linux系統中,除了第一個進程(0號進程),其他進程都會有一個或多個子進程,所以進程是樹形結構(pstree查看)。 進程編號 0 通常被稱為kernel、sched或swapper,而進程編號 1 稱為init。 init 是所有進程的父進程或祖先進程。 在系統中,對於過早消亡(die)的進程,它的父進程會被重新指定為init。 在關機時,進程的退出是根據ID由大到小的順序依次執行,init進程結束後,系統便終止。
PS(process status) 命令用於查看系統正在運行的進程。(某一個時間點上) - ps aux (FreeBSD風格) ps elf(System V)風格 ps 命令說明:
USER 進程的擁有者
PID 進程的ID值。進程的ID值自0開始,每遇到一個新進程就加一。
PPID 父進程的ID。
%CPU 進程占用CPU百分比。
%MEM 占用內存的百分比。
VSZ 進程虛擬大小(bytes字節(包含code+data+stack) )
WCHAN 正在等待的進程資源
NI 進程的nice值,優先級。(優先級的范圍是從 -20(最大優先級) 到 19 (最小優先級)。)
RSS 駐留中頁的數量
TTY 終端ID
STAT 進程狀態
START 進程啟動的時間
TIME 進程消耗CPU的時間
COMMAND 進程名稱和參數
stat顯示的進程狀態信息:
D 不可中斷的睡眠狀態(通常是I/O進程),收到信號不會被喚醒。
R 正在運行的 或 運行隊列中等待的(可運行)
S 可中斷睡眠狀態(休眠中,受阻。在等待中斷的到來或某個信號都可以將其喚醒轉換到就緒狀態)
T 暫停狀態,當進程收到SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU時,就會進入暫停狀態。
W 進入內存交換(從內核2.6開始無效)
X 死掉的進程
Z 僵屍進程 ,進程已終止, 但進程描述符存在, 直到父進程調用wait()系統調用後釋放
< 優先級高的進程
N 優先級低的進程
L 有些頁被鎖進內存(實時和定制的IO)
s 進程的領導者(在它之下有子進程)
l 多線程進程(使用CLONE_THREAD函數創造)
+ 位於後台的進程
- top 系統實時進程信息
5. 進程的屬性 一個進程是一個程序的一次執行過程(有開始有結束),程序是靜態的,它是保存在磁盤上的可執行代碼和數據集合,進程是一個動態的概念。程序是一個進程指令的集合,它可以啟用一個或多個進程,同時,程序只占用磁盤空間,而不占用系統運行資源,而進程僅僅占用系統內存空間,是動態的、可變的,關閉進程,占用的內存資源隨之釋放。 一個進程由如下元素構成: - 程序的讀取上下文,它表示程序讀取執行的狀態。 - 程序當前的執行目錄
- 程序服務的文件和目錄 - 程序的訪問權限
- 內存和其它分配給進程的系統資源
Linux一個進程在內存中由3部分數據:數據段、堆棧段、代碼段。 - 代碼段: 存放了程序代碼的數據。(多個進程運行同一個程序時使用同一個代碼段) - 數據段: 存放程序的全局變量、常數及動態分配的數據空間。 - 堆棧段: 存放子程序的返回地址、子程序的參數及程序的局部變量。堆棧段包括在進程控制塊(Process Control Block)中。PCB處於進程核心堆棧的底部,無需額外分配空間。
5. Linux 系統的進程狀態: 用戶狀態 進程在用戶狀態下運行的狀態(進程在執行用戶自己的代碼) 內核狀態 進程在內核狀態下運行的狀態(進程在內核代碼中運行)
內存中就緒 進程沒有執行,但出於就緒狀態,只要內核調度它,就可以執行
內存中睡眠 進程正在睡眠,並且進程存儲在內存中,還有被交換到swap
就緒且換入 進程處於就緒狀態,但是必須把它換入內存,內核才能再次調度它運行
睡眠且換出 進程正在睡眠,且被換出內存
被搶先 進程從內核狀態返回用戶狀態時,內核搶先它做了上下文切換,調度了另一個進程,原先那個進程就處於被搶先狀態。(在內核狀態下的進程不能被其他進程搶占)
創建狀態 進程剛被創建。該進程存在,但既不是就緒狀態,也不是睡眠狀態。這個狀態是除了進程0以外的所有進程的最初狀態。 僵死狀態(zombie) 進程調用exit結束,進程不再存在,但是進程表項中仍有記錄(進程描述符存在),該記錄可由父進程收集。
一個進程在其生存周期內,處於一組不同的狀態下,稱為進程狀態。進程狀態保存在進程任務結構的state字段中。
解釋:
運行狀態(TASK_RUNNING)
指進程正在被CPU執行,或者已經准備就緒(在運行隊列中等待,沒有被CPU執行,也稱為就緒運行狀態),隨時可由調度程序執行,則稱該進程處於運行狀態(running)。該狀態下有三種情況:用戶運行態、內核運行態、就緒態。 - 就緒態:當系統資源已經可用時,進程就被喚醒而進入准備運行狀態。
可中斷睡眠狀態(TASK_INTERRUPTIBIE) 進程正在等待系統資源的一種狀態,稱其處於睡眠等待狀態。可中斷睡眠狀態是指可以被中斷的睡眠等待狀態。當系統產生一個中斷或者釋放了進程正在等待的資源時,或者進程收到一個信號,都可以喚醒進程轉換到就緒狀態(可運行狀態)。
不可中斷睡眠狀態(TASK_UNINTERRUPTIBIE) 指不可以被中斷的睡眠等待狀態,不可以被收到的信號喚醒,只有被wake_up()函數喚醒時,才可以裝換到可運行的就緒狀態。處在該狀態下的進程通常需要不受干擾的等待,或者所等待的事件很快發生。
暫停狀態(TASK_STOPPED) 當進程收到信號SIGSTOP、SIGTSTP、SIGTTIN或SIGTTOU時,就會進入暫停狀態。可以向其發送SIGCONT信號,讓進程轉換到可運行狀態。
僵死狀態(TASK_ZOMBIE) 進程已經停止,但其父進程還沒有調用wait()詢問其狀態的進程處於僵死狀態。(僵死進程的任務數據結構信息還需要保留著,一旦父進程調用wait(),取得其信息,這些數據結構信息就會被釋放。)
6.進程的切換: 當一個進程的時間片用完時,系統就會使用調度程序強制切換到其他的去執行。 當進程在內核態執行時,需要等待系統的某個資源時,此進程就會調用 sleep_on() 或 interruptible_sleep_on()就進入睡眠狀態(TASK_INTERRUPTIBIE 或 TASK_UNINTERRUPTIBIE),自願放棄CPU的使用權,而讓調度程序去執行其他進程。 只有當進程從 “內核運行態” 轉移到 “睡眠狀 態” 時,內核才會進行進程切換操作。 在內核態下運行的進程不能被其它進程搶占,而且一個進程不能改變另一個進程的狀態。為了避免進程切換時造成的內核數據錯誤,內核在執行臨界區代碼時會禁止一切中斷。
7.linux 進程與任務調度
在Linux系統中,每個進程都有一個進程號(PID),用於系統識別和調度進程。 啟動一個進程有兩個主要途徑:手工啟動 和 調度啟動。 - 調度啟動是事先設置,根據用戶要求自行啟動。 - 手工啟動進程是由用戶輸入命令,直接啟動一個進程。 手工啟動的進程分兩種:前台進程 和 後台進程 (1)前台進程 shell執行前台進程的格式: command 對於前台啟動的進程,shell會等待進程執行完畢。 (2)後台進程 shell執行前台進程的格式: command & 對於前台啟動的進程,shell並不等待進程執行完畢。
前後台進程調度: 終止進程: -前台:Ctrl+c -後台:kill(向內核發送一個系統操作信號和進程的PID,然後內核就可以停止該進程) 前台進程轉後台: Ctrl+z 暫停進程,然後 bg 命令,將當前進程轉入後台 後台轉前台: fg (將當前進程轉入前台) 多個後台進程的調度方法: shell 中有兩個以上的後台進程同時運行,需要用到 jobs 命令,將一個特定的後台進程帶到前台。 jobs 命令是用來判斷所有被掛起(停止)的進程、後台作業進程號,以及哪一個是當前進程。
[root@web1 ~]# jobs # 列出當前被掛起的進程&後台進程
[1] Stopped sleep 101
[2] Stopped sleep 102
[3]- Stopped sleep 103
[4]+ Stopped sleep 104
[root@web1 ~]# bg # bg 將當前進程(+標識)帶入後台 [4]+ sleep 104 & [4] Done sleep 104
[root@web1 ~]# jobs -l # 第二列為PID
[1] 21224 停止 sleep 101
[2] 21225 停止 sleep 102
[3]- 21226 停止 sleep 103
[4]+ 21235 停止 sleep 104
[root@web1 ~]# bg %2 # 將作業號為2的進程帶入後台
[2] sleep 102 &
[root@web1 ~]# jobs
[1] Stopped sleep 101
[2] Done sleep 102
[3]- Stopped sleep 103
[4]+ Stopped sleep 104
[root@web1 ~]# bg %1 %2 %3 [1] sleep 100 & [2] sleep 101 & [3]- sleep 102 & [root@web1 ~]# jobs [1] Running sleep 100 & [2] Running sleep 101 & [3]- Running sleep 102 & [4]+ Stopped sleep 103
jobs 顯示當前會話的作業狀態輸出四列: <任務編號> <當前進程> <進程狀態> <進程內容> + 標志當前進程 - 標志前一個進程
bg 默認將當前進程帶入後台
eg.
bg %n1 %n2 %n2 將指定作業號的進程帶入後台
kill %n 終止指定作業號的進程
作業號可以與 wait fg kill bg 等命令一起使用,只要在作業號前加上%前綴。
Linux的任務調度方式: crontab 和 at crontab是調度重復性的系統任務;at是在特定時間調用單個系統任務。
8. 利用 pstree 監控系統進程
pstree 命令以樹形結構顯示程序和進程之間的關系,使用格式如下: pstree [-a|-c|-n|-p|-u|-l] [-h|-H 進程號] [進程號 | 用戶]
Child threads of a process are found under the parent process and are shown with the process name in curly braces(花括號).
e.g.
icecast2---13*[{icecast2}]
顯示進程樹。
-a 顯示命令行參數,即顯示啟動每個進程對應的完整指令,包含啟動進程的路徑、參數等等。
-c 不壓縮雷同的子樹,即顯示父進程和子進程(如果存在的話)
-h 高亮顯示當前進程及其祖先
-H 進程號 高亮顯示 "進程號" 指定的進程當及其祖先
-l 不截斷長行
-n 輸出按進程號排序
-p 顯示進程號;隱含 -c
-u 顯示進程對應的用戶名
進程號 從指定的 "進程號" 開始顯示進程樹,缺省是1(init)
用戶 僅顯示從該 "用戶" 的進程開始的進程樹
pstree清楚的顯示了程序和進程之間的關系,如果不指定進程的PID號,或者不指定用戶名稱,則將以init進程為根進程,顯示系統的所有程序和進程信息,若指定用戶或PID,則將以用戶或PID為根進程,顯示用戶或PID對應的所有程序和進程。
[root@web1 ~]# pstree -h
init─┬─ManagementAgent───2*[{ManagementAgen}]
├─VGAuthService
├─atd
├─crond
├─dnsmasq
├─httpd───5*[httpd]
├─ksmtuned───sleep
├─libvirtd───10*[{libvirtd}]
├─6*[mingetty]
├─mysqld_safe───mysqld───9*[{mysqld}]
├─named───4*[{named}]
├─pure-ftpd
├─rpc.idmapd
├─rpc.mountd
├─rpc.rquotad
├─rpcbind
├─rsyslogd───3*[{rsyslogd}]
├─smbd───smbd
├─sshd───sshd───bash───pstree
├─udevd───2*[udevd]
├─vmtoolsd───{vmtoolsd}
├─vmware-vmblock-───3*[{vmware-vmblock}]
└─vsftpd
例如: (1)如果想知道某個用戶都啟動了那些進程的話,pstree 用戶名 就可以實現:
[root@web1 ~]# pstree mysql // 顯示mysql用戶啟動了那些進程
mysqld───9*[{mysqld}] // 輸出顯示 mysqld 進程擁有9個子進程
詳細的包含子進程的信息如下:
[root@web1 ~]# pstree -c -p mysql // 包含進程號,31265 下面工 9 個 子進程
mysqld(31265)─┬─{mysqld}(31267)
├─{mysqld}(31268)
├─{mysqld}(31269)
├─{mysqld}(31270)
├─{mysqld}(31274)
├─{mysqld}(31275)
├─{mysqld}(31276)
├─{mysqld}(31277)
└─{mysqld}(31278)
(2) 也可以通過指定的PID查看對應的進程信息。
[root@web1 ~]# pstree 31747 -c -p
httpd(31747)─┬─httpd(31748)
├─httpd(31749)
├─httpd(31750)
├─httpd(31751)
└─httpd(31752)
(3) 顯示啟動時的參數等信息
[root@web1 ~]# pstree 31747 -a -c -p
httpd,31747 -k start
├─httpd,31748 -k start
├─httpd,31749 -k start
├─httpd,31750 -k start
├─httpd,31751 -k start
└─httpd,31752 -k start
9. 通過 lsof 監控系統進程
lsof - list open files
lsof全名list opene files,也就是列舉系統中已經被打開的文件,通過lsof,我們就可以根據文件找到對應的進程信息,也可以根據進程信息找到進程打開的文件。 lsof指令功能強大,這裡介紹“-c,-g,-p,-i”這四個最常用參數的使用。更詳細的介紹請參看man lsof。
(1) lsof filename 顯示使用filename文件的進程 如果想知道某個特定文件有那個進程使用,可以用 lsof filename 方式得到,例如:
[root@web1 ~]# lsof /var/log/messages
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd 1461 root 1w REG 8,3 321741 948875 /var/log/messages
可以得知,/var/log/messages文件是由 進程rsyslogd在使用
(2)lsof -c 進程名 顯示進程現在打開的文件
例如:
[root@web1 ~]# lsof -c mysqld |head -10
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld_sa 31149 root cwd DIR 8,3 4096 815718 /usr/local/mysql
mysqld_sa 31149 root rtd DIR 8,3 4096 2 /
mysqld_sa 31149 root txt REG 8,3 904872 130567 /bin/bash
mysqld_sa 31149 root mem REG 8,3 99154480 786050 /usr/lib/locale/locale-archive
mysqld_sa 31149 root mem REG 8,3 1921176 652830 /lib64/libc-2.12.so
mysqld_sa 31149 root mem REG 8,3 19536 652836 /lib64/libdl-2.12.so
mysqld_sa 31149 root mem REG 8,3 135896 652872 /lib64/libtinfo.so.5.7
mysqld_sa 31149 root mem REG 8,3 154528 652823 /lib64/ld-2.12.so
mysqld_sa 31149 root mem REG 8,3 26060 786308 /usr/lib64/gconv/gconv-modules.cache
上例顯示了mysqld進程打開的文件信息, FD列表示文件描述符, TYPE列顯示文件的類型, SIZE列顯示文件的大小, NODE列顯示本地文件的node碼, NAME列顯示文件的全路徑或掛載點。
(3)lsof -g 進程號 顯示指定的進程組打開的文件情況
例如:
[root@web1 ~]# lsof -g 31747 |head -10
COMMAND PID PGID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 31747 31747 root cwd DIR 8,3 4096 2 /
httpd 31747 31747 root rtd DIR 8,3 4096 2 /
httpd 31747 31747 root txt REG 8,3 2130662 949131 /usr/local/apache2/bin/httpd
httpd 31747 31747 root mem REG 8,3 1857772 923397 /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/mongo.so
httpd 31747 31747 root mem REG 8,3 1463666 948869 /usr/local/php/lib/php/extensions/no-debug-non-zts-20131226/redis.so
httpd 31747 31747 root mem REG 8,3 99154480 786050 /usr/lib/locale/locale-archive
httpd 31747 31747 root mem REG 8,3 65928 652846 /lib64/libnss_files-2.12.so
httpd 31747 31747 root mem REG 8,3 122040 652904 /lib64/libselinux.so.1
httpd 31747 31747 root mem REG 8,3 110960 652856 /lib64/libresolv-2.12.so
....
....
httpd 31752 31747 daemon mem REG 8,3 183080 652944 /lib64/libpcre.so.0.0.1 httpd 31752 31747 daemon mem REG 8,3 596272 652838 /lib64/libm-2.12.so httpd 31752 31747 daemon mem REG 8,3 154528 652823 /lib64/ld-2.12.so httpd 31752 31747 daemon DEL REG 0,4 261274 /dev/zero httpd 31752 31747 daemon 0r CHR 1,3 0t0 4549 /dev/null httpd 31752 31747 daemon 1w CHR 1,3 0t0 4549 /dev/null httpd 31752 31747 daemon 2w REG 8,3 7375 951180 /usr/local/apache2/logs/error_log httpd 31752 31747 daemon 3u sock 0,6 0t0 261254 can't identify protocol httpd 31752 31747 daemon 4u IPv6 261255 0t0 TCP *:http (LISTEN) httpd 31752 31747 daemon 5r FIFO 0,8 0t0 261270 pipe httpd 31752 31747 daemon 6w FIFO 0,8 0t0 261270 pipe httpd 31752 31747 daemon 7w REG 8,3 4877 951374 /usr/local/apache2/logs/dummy-hos t.example.com-error_log httpd 31752 31747 daemon 8w REG 8,3 1997 951181 /usr/local/apache2/logs/access_lo g httpd 31752 31747 daemon 9w REG 8,3 3482 951777 /usr/local/apache2/logs/dummy-hos t.example.com-access_log httpd 31752 31747 daemon 10u REG 0,9 0 4547 [eventpoll]
其中,PGID列表示進程組的ID編號。上面輸出,顯示了httpd程序當前打開的所有文件、設備、套接字等
(4)lsof -p pid號 通過進程號顯示程序打開的所有文件及相關進程,例如,想知道init進程打開了哪些文件的話,可以執行“lsof -p 1”命令,輸出結果如下:
[root@web1 ~]# lsof -p 1
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 8,3 4096 2 /
init 1 root rtd DIR 8,3 4096 2 /
init 1 root txt REG 8,3 150352 261165 /sbin/init
init 1 root mem REG 8,3 65928 652846 /lib64/libnss_files-2.12.so
init 1 root mem REG 8,3 1921176 652830 /lib64/libc-2.12.so
init 1 root mem REG 8,3 90880 652945 /lib64/libgcc_s-4.4.7-20120601.so.1
init 1 root mem REG 8,3 43880 652858 /lib64/librt-2.12.so
init 1 root mem REG 8,3 142640 652854 /lib64/libpthread-2.12.so
init 1 root mem REG 8,3 265728 652881 /lib64/libdbus-1.so.3.4.0
init 1 root mem REG 8,3 39896 652964 /lib64/libnih-dbus.so.1.0.0
init 1 root mem REG 8,3 101920 652966 /lib64/libnih.so.1.0.0
init 1 root mem REG 8,3 154528 652823 /lib64/ld-2.12.so
init 1 root 0u CHR 1,3 0t0 4549 /dev/null
init 1 root 1u CHR 1,3 0t0 4549 /dev/null
init 1 root 2u CHR 1,3 0t0 4549 /dev/null
init 1 root 3r FIFO 0,8 0t0 7796 pipe
init 1 root 4w FIFO 0,8 0t0 7796 pipe
init 1 root 5r DIR 0,10 0 1 inotify
init 1 root 6r DIR 0,10 0 1 inotify
init 1 root 7u unix 0xffff880037695440 0t0 7797 @/com/ubuntu/upstart
(5)lsof -i 通過監聽指定的協議、端口、主機等信息,顯示符合條件的進程信息
lsof -i address: [46][proto][@host|addr][:{service_list | port_list}] // 緊挨著
46:4代表IPv4,6代表IPv6。
protocol:傳輸協議,可以是TCP或UDP。
hostname:主機名稱或者IP地址。
service:進程的服務名,例如nfs、ssh、ftp等。
port:系統中服務對應的端口號。例如http服務默認對應80,ssh服務默認對應22等等。
例如: 查看系統中 tcp 協議對應的80端口的進程信息
[root@web1 ~]# lsof -i tcp:80
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 31747 root 4u IPv6 261255 0t0 TCP *:http (LISTEN)
httpd 31748 daemon 4u IPv6 261255 0t0 TCP *:http (LISTEN)
httpd 31749 daemon 4u IPv6 261255 0t0 TCP *:http (LISTEN)
httpd 31750 daemon 4u IPv6 261255 0t0 TCP *:http (LISTEN)
httpd 31751 daemon 4u IPv6 261255 0t0 TCP *:http (LISTEN)
httpd 31752 daemon 4u IPv6 261255 0t0 TCP *:http (LISTEN)
查看udp協議對應的21端口的進程信息
[root@web1 ~]# lsof -i tcp:21
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
vsftpd 1788 root 3u IPv4 12271 0t0 TCP *:ftp (LISTEN)
[root@web1 ~]# lsof -i tcp:2121
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
pure-ftpd 2134 root 4u IPv4 12831 0t0 TCP *:scientia-ssdb (LISTEN)
udp協議 53端口的信息
[root@web1 ~]# lsof -i [email protected]:53
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
named 1553 named 512u IPv4 11398 0t0 UDP localhost:domain
小結:通過lsof命令能夠清楚的了解進程和文件的對應關系。