11. 進程管理

程序和進程

https://www.jianshu.com/p/07173e5e333a

  • 程序 (program):通常爲 binary program ,放置在儲存媒體中 (如硬盤、光盤、軟盤、磁帶等), 爲實體文件的型態存在;

  • 進程 (process):程序被觸發後,執行者的權限與屬性、程序的程序碼與所需數據等都會被載入內存中, 操作系統並給予這個內存內的單元一個識別碼 (PID),可以說,進程就是一個正在運行中的程序。

子進程和父進程

fork and exec:程序調用的流程

子程序與父程序之間的關係還挺複雜的,最大的複雜點在於程序互相之間的調用。在 Linux 的程序調用通常稱爲 fork-and-exec 的流程 [1]!程序都會藉由父程序以複製 (fork) 的方式產生一個一模一樣的子程序, 然後被複製出來的子程序再以 exec 的方式來執行實際要進行的程序,最終就成爲一個子程序的存在。 整個流程有點像下面這張圖:

  1. 系統先以 fork 的方式複製一個與父程序相同的暫存程序,這個程序與父程序唯一的差別就是 PID 不同! 但是這個暫存程序還會多一個 PPID 的參數,PPID 就是父程序的程序識別碼啦!
  2. 然後,暫存程序開始以 exec 的方式載入實際要執行的程序,以上述圖示來講,新的程序名稱爲 qqq ,最終子程序的程序碼就會變成 qqq 了

系統或網絡服務:常駐在內存的程序

一直在執行的程序,就是常駐在內存當中的程序。

常駐在內存當中的程序通常都是負責一些系統所提供的功能以服務使用者各項任務,因此這些常駐程序就會被我們稱爲:服務 (daemon)。

系統的服務非常的多, 不過主要大致分成系統本身所需要的服務,例如 crond 計劃任務 ,還有 rsyslogd 日誌服務等等的。還有一些則是負責網絡連接的服務,例如 Apache, named, postfix, vsftpd... 等等的。這些網絡服務的程序被執行後,他會啓動一個可以負責網絡監聽的端口 (port) ,以提供外部用戶端 (client) 的連線請求。

一般 daemon 類型的程序都會加上 d 在文件名後頭,因爲 Linux 希望我們可以簡單的判斷該程序是否爲 daemon

多人、多任務、多環境

多重登陸環境的七個基本終端窗口:
在 Linux 當中,默認提供了六個文字界面登陸窗口,以及一個圖形界面,你可以使用 [Alt]+[F1].....[F7] 來切換不同的終端機界面,而且每個終端機界面的登陸者還可以不同人

查看系統中的進程

ps :獲取到某個時間點的程序運行情況(靜態)

ps   aux   查看所有的進程信息,注意這裏的 aux x選項沒有短橫線

選項與參數:
-A  :所有的 process 均顯示出來,與 -e 具有同樣的效用;
-a  :不與 terminal 有關的所有 process ;
-u  :有效使用者 (effective user) 相關的 process ;
x   :通常與 a 這個參數一起使用,可列出較完整信息。

輸出格式:
l   :較長、較詳細的將該 PID 的的信息列出;
j   :工作的格式 (jobs format)
-f  :做一個更爲完整的輸出。

ps aux 輸出各字段意義

USER:  該 process 屬於那個使用者帳號的?

PID :  該 process 的程序識別碼。

%CPU:  該 process 使用掉的 CPU 資源百分比;

%MEM:  該 process 所佔用的實體內存百分比;

VSZ :  該 process 使用掉的虛擬內存量 (KBytes)

RSS :  該 process 佔用的固定的內存量 (KBytes)

TTY :  該 process 是在那個終端機上面運行,若與終端機無關則顯示 ?,另外, tty1-tty6 是本機上面的登陸者程序,若爲 pts/0 等等的,則表示爲由網絡連接進主機的程序。

STAT:  該程序目前的狀態,狀態顯示與 ps -l 的 S 旗標相同 (R/S/T/Z)

START: 該 process 被觸發啓動的時間;

TIME : 該 process 實際使用 CPU 運行的時間。

COMMAND:該程序的實際指令爲何?



S:代表這個程序的狀態 (STAT),主要的狀態有:

  • R (Running):該程序正在運行中;
  • S (Sleep):該程序目前正在睡眠狀態(idle),但可以被喚醒(signal)。
  • D :不可被喚醒的睡眠狀態,通常這支程序可能在等待 I/O 的情況(ex>打印)
  • T :停止狀態(stop),可能是在 jobs 控制(後臺暫停)
  • Z (Zombie):殭屍狀態,程序已經終止但卻無法被移除至內存外。

什麼是殭屍進程

我們必須要知道的是“殭屍 (zombie) ”程序是什麼? 通常,造成殭屍程序的成因是因爲該程序應該已經執行完畢,或者是因故應該要終止了, 但是該程序的父程序卻無法完整的將該程序結束掉,而造成那個程序一直存在內存當中。 如果你發現在某個程序的 CMD 後面還接上 <defunct> 時,就代表該程序是殭屍程序啦,例如:

當系統不穩定的時候就容易造成所謂的殭屍程序,可能是因爲程序寫的不好啦,或者是使用者的操作習慣不良等等所造成。 如果你發現系統中很多殭屍程序時,記得啊!要找出該程序的父程序,然後好好的做個追蹤,好好的進行主機的環境最優化啊! 看看有什麼地方需要改善的,不要只是直接將他 kill 掉而已呢!不然的話,萬一他一直產生,那可就麻煩了!

事實上,通常殭屍程序都已經無法控管,而直接是交給 systemd 這支程序來負責了,偏偏 systemd 是系統第一支執行的程序, 他是所有程序的父程序!我們無法殺掉該程序的 (殺掉他,系統就死掉了!),所以囉,如果產生殭屍程序, 而系統過一陣子還沒有辦法通過核心非經常性的特殊處理來將該程序刪除時,那你只好通過 reboot 的方式來將該程序抹去了!

top 動態

top 命令

選項與參數:
-d :後面可以接秒數,就是整個程序畫面更新的秒數。默認是 5 秒;
-b :以批次的方式執行 top ,還有更多的參數可以使用喔!
通常會搭配數據流重導向來將批次的結果輸出成爲文件。
-n :與 -b 搭配,意義是,需要進行幾次 top 的輸出結果。
-p :指定某些個 PID 來進行觀察監測而已。
在 top 執行過程當中可以使用的按鍵指令:
? :顯示在 top 當中可以輸入的按鍵指令;
P :以 CPU 的使用資源排序顯示;
M :以 Memory 的使用資源排序顯示;
N :以 PID 來排序喔!
T :由該 Process 使用的 CPU 時間累積 (TIME+) 排序。
k :給予某個 PID 一個訊號 (signal)
r :給予某個 PID 重新制訂一個 nice 值。
q :離開 top 軟件的按鍵。

top - 19:55:28 up 11:10,  1 user,  load average: 0.00, 0.01, 0.05
Tasks: 160 total,   1 running, 159 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni, 99.9 id,  0.0 wa,  0.0 hi,  0.0 si,
KiB Mem : 16251468 total, 15535360 free,   443400 used,   272708 buff/c
KiB Swap:  8257532 total,  8257532 free,        0 used. 15482496 avail

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+
 3711 root      20   0  157760   2324   1632 R   0.7  0.0   0:00.02
   10 root      20   0       0      0      0 S   0.3  0.0   0:13.99
    1 root      20   0  191188   4188   2516 S   0.0  0.0   0:01.91
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.00
    3 root      20   0       0      0      0 S   0.0  0.0   0:00.12
    5 root       0 -20       0      0      0 S   0.0  0.0   0:00.00
    7 root      20   0       0      0      0 S   0.0  0.0   0:00.03
    8 root      rt   0       0      0      0 S   0.0  0.0   0:00.16
    9 root      20   0       0      0      0 S   0.0  0.0   0:00.00
   11 root      rt   0       0      0      0 S   0.0  0.0   0:00.66
   12 root      rt   0       0      0      0 S   0.0  0.0   0:00.08
   13 root      rt   0       0      0      0 S   0.0  0.0   0:00.04
   14 root      20   0       0      0      0 S   0.0  0.0   0:00.00
   16 root       0 -20       0      0      0 S   0.0  0.0   0:00.00
   17 root      20   0       0      0      0 S   0.0  0.0   0:00.07
   18 root      rt   0       0      0      0 S   0.0  0.0   0:00.07
   19 root      rt   0       0      0      0 S   0.0  0.0   0:00.04


第一行

19:55:28 系統當前時間
up 11:10 系統開機到現在經過了 11 小時 10 分鐘了
1 users : 當前 1 個用戶在線
load average: 0.00, 0.01, 0.05 系統1分鐘、5分鐘、15分鐘的CPU負載信息

第二行

Tasks: 任務
160 total, 總共160個任務,就是 160 個進程
1 running, 1 個進程是 運行狀態
159 sleeping, 159 個進程是 休眠狀態
0 stopped, 0 個進程是 停止狀態
0 zombie, 0 個進程是僵死狀態

第三行

%Cpu(s): 表示這一行顯示CPU總體信息 ,單位是百分比

0.0 us, 用戶態進程佔用CPU時間百分比,不包含renice值爲負的任務佔用的CPU的時間。

0.0 sy, 內核佔用CPU時間百分比
0.0 ni, 改變過優先級的進程佔用CPU的百分比
99.9 id, 空閒CPU時間百分比
0.0 wa, 等待I/O的CPU時間百分比
0.0 hi, CPU硬中斷時間百分比
0.0 si, CPU軟中斷時間百分比

注:這裏顯示數據是所有cpu的平均值,如果想看每一個cpu的處理情況,按1即可;收起,再次按1;

第四行

KiB Mem : 內存信息
16251468 total, 物理內存總容量
15535360 free, 空閒物理內容容量
443400 used, 已使用的物理內存
272708 buff/c 用作內核緩存的物理內存量

第五行

KiB Swap: 交互分區
8257532 total, 總共
8257532 free, 空閒
0 used. 已用
15482496 avail 有效提供給程序使用的內存,這個並不是 Swap 分區的容量

需要注意的是,free表示的是當前完全沒有被程序使用的內存;而cache在有需要時,是可以被釋放出來以供其它進程使用的(當然,並不是所有cache都可以釋放,比如當前被用作ramfs的內存)。而available才真正表明系統目前可以提供給應用程序使用的內存。

第六行

PID:進程的ID
USER:進程擁有者
PR:Priority 的簡寫,進程的優先級別,越小越優先被執行
NI:Nice 的簡寫,與 Priority 有關,也是越小越早被執行;
VIRT:進程佔用的虛擬內存
RES:進程佔用的物理內存
SHR:進程使用的共享內存
S:進程的狀態。S表示休眠,R表示正在運行,Z表示僵死狀態,N表示該進程優先值爲負數
%CPU:進程佔用CPU的使用率
%MEM:進程使用的物理內存和總內存的百分比
TIME+:該進程啓動後佔用的總的CPU時間,即佔用CPU使用時間的累加值。

top 常用交互命令

q:退出top命令
<Space>:立即刷新
s:設置刷新時間間隔
c:顯示命令完全模式
t::顯示或隱藏進程和CPU狀態信息
m:顯示或隱藏內存狀態信息
l:顯示或隱藏uptime信息
f:增加或減少進程顯示標誌
S:累計模式,會把已完成或退出的子進程佔用的CPU時間累計到父進程的MITE+
P:按%CPU使用率排行
T:按MITE+排行
M:按%MEM排行
u:指定顯示用戶進程
r:修改進程renice值
kkill:進程
i:只顯示正在運行的進程
W:保存對top的設置到文件~/.toprc,下次啓動將自動調用toprc文件的設置。
h:幫助命令。
q:退出

pstree 進程樹

pstree
選項與參數:
-A  :各程序樹之間的連接以 ASCII 字符來連接;
-U  :各程序樹之間的連接以萬國碼的字符來連接。在某些終端接口下可能會有錯誤;
-p  :並同時列出每個 process 的 PID;
-u  :並同時列出每個 process 的所屬帳號名稱。
[root@kvm-docker ~]# pstree -A -p -u

進程的管理

進程之間是可以互相控制的!舉例來說,你可以關閉、重新啓動服務器軟件,服務器軟件本身是個進程, 你既然可以讓她關閉或啓動,當然就是可以控制該進程。

如何控制進程?

通過給予該進程一個信號 (signal) 去告知該進程你想要讓她作什麼。

都有哪些信號?

命令
kill  -l

輸出

kill -l
 1) SIGHUP   2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX


主要的訊號代號與名稱對應及內容是:

代號 名稱 內容
1 SIGHUP 啓動被終止的進程,可讓該 PID 重新讀取自己的配置文件,類似重新啓動
2 SIGINT 相當於用鍵盤輸入 [ctrl]-c 來中斷一個進程的進行
9 SIGKILL 代表強制中斷一個進程的進行,如果該進程運行到一半, 那麼尚未完成的部分可能會有“半產品”產生,類似 vim會有 .filename.swp 保留下來。
15 SIGTERM 以正常的結束進程來終止該程序的運行。由於是正常的終止, 所以後續的動作會將他完成。不過,如果該進程已經發生問題,就是無法使用正常的方法終止時, 輸入這個信號也是沒有用的。
19 SIGSTOP 相當於用鍵盤輸入 [ctrl]-z 來暫停一個進程的運行

一般來說,你只要記得1, 9, 15 這三個號碼的意義即可。那麼我們如何傳送一個訊號給某個程序呢?就通過 killkillall 。下面分別來看看:

kill    -信號代號     進程的PID號
或者
kill    -信號名稱     進程的PID號

killall   -信號   命名名稱

查詢進程和已打開文件的關係

fuser:藉由文件(或文件系統)找出正在使用該文件的程序

 fuser  [-umv]  [-k [i]  [-signal]]  file/dir

選項與參數:
-u  :除了程序的 PID 之外,同時列出該程序的擁有者;
-m  :後面接的那個文件名會主動的上提到該文件系統的最頂層,對 umount 不成功很有效!
-v  :可以列出每個文件與程序還有指令的完整相關性!
-k  :找出使用該文件/目錄的 PID ,並試圖以 SIGKILL 這個訊號給予該 PID;
-i  :必須與 -k 配合,在刪除 PID 之前會先詢問使用者意願!
-signal:例如 -1 -15 等等,若不加的話,默認是 SIGKILL (-9) 囉!

找出目前所在目錄的使用 PID/所屬帳號/權限

[root@kvm-docker ~]# fuser -uv .
                     用戶     進程號 權限   命令
/root:               root       2379 ..c.. (root)bash
                     root       2419 ..c.. (root)sh
                     root       2420 ..c.. (root)ntpdate

權限部分

c :此程序在當前的目錄下(非次目錄);
e :可被觸發爲執行狀態;
f :是一個被打開的文件;
r :代表頂層目錄 (root directory);
F :該文件被打開了,不過在等待迴應中;
m :可能爲分享的動態函數庫;

lsof :列出被程序所打開的文件文件名

[root@study ~]# lsof [-aUu] [+d]
選項與參數:
-a  :多項數據需要“同時成立”才顯示出結果時!
-U  :僅列出 Unix like 系統的 socket 文件類型;
-u  :後面接 username,列出該使用者相關程序所打開的文件;
+d  :後面接目錄,亦即找出某個目錄下面已經被打開的文件!

[root@shark ~]# lsof /var/log/messages
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
abrt-watc   732 root    4r   REG  253,0    50234 41435338 /var/log/messages
rsyslogd  14809 root    9w   REG  253,0    50234 41435338 /var/log/messages
[root@shark ~]# lsof -U  -a -u 0 |grep nginx
nginx       706 root    3u  unix 0xffff8800d662d800      0t0  16052 socket
nginx       706 root    9u  unix 0xffff8800d662cc00      0t0  16053 socket
nginx       706 root   10u  unix 0xffff8800d67cf800      0t0  16054 socket
nginx       706 root   11u  unix 0xffff8800d67cfc00      0t0  16055 socket

工作管理 jobs

jobs

將一個進程放到後臺。

vim  ~/.bashrc

之後按下 Ctrl+z 將進程放到後臺,此時會看到是停止狀態

查看後臺的工作進程

jobs   -l

fg 調取後臺進程到前臺

➜  src jobs
[1]  + suspended  vi thanks.c
➜  src jobs
[1]  + suspended  vi thanks.c
➜  src fg %1

bg 把後臺的暫停的進程啓動

➜  src find /

接着按下 `Ctrl+z`

➜  src jobs
[1]  + suspended  find /

➜  src fg %1

製作高負載 cpu

root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
[root@study ~]# echo "scale=100000; 4*a(1)" | bc -lq &
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章