Linux深入探索15-進(jìn)程和作業(yè)控制

----- 最近更新【2022-01-25】-----

本文目錄結(jié)構(gòu)預(yù)覽:

  • 一、簡(jiǎn)介
  • 二调衰、內(nèi)核管理進(jìn)程的方式
    1、調(diào)度器 與 CPU 時(shí)間
    2自阱、系統(tǒng)調(diào)用
  • 三嚎莉、父進(jìn)程與子進(jìn)程
    1、概念
    2沛豌、進(jìn)程分叉到死亡
    3趋箩、第一個(gè)進(jìn)程:init
  • 四、作業(yè)控制-介紹
    1加派、概念
    2叫确、作業(yè)控制相關(guān)工具
    3、作業(yè)與進(jìn)程的區(qū)別
  • 五芍锦、作業(yè)控制-操作
    1竹勉、在后臺(tái)運(yùn)行作業(yè):&
    2、掛起作業(yè):^Z
    3娄琉、掛起 shell:suspend
    4次乓、顯示作業(yè)列表:jobs
    5吓歇、將作業(yè)移至前臺(tái):fg
    6、將作業(yè)移至后臺(tái):bg
  • 六票腰、進(jìn)程查找-ps
    1城看、ps 簡(jiǎn)介
    2、常用選項(xiàng)
    3杏慰、常見(jiàn)的數(shù)據(jù)列
    4测柠、嘗試追蹤一個(gè)進(jìn)程的父進(jìn)程 ID
    5、查找指定名稱(chēng)的進(jìn)程
  • 七缘滥、進(jìn)程管理
    1鹃愤、監(jiān)視系統(tǒng)進(jìn)程:top
    2、顯示進(jìn)程樹(shù):pstree
    3完域、向進(jìn)程發(fā)送信號(hào):kill
  • 八软吐、參考

一、簡(jiǎn)介

在 Unix 系統(tǒng)中吟税,每個(gè)對(duì)象或者用文件表示凹耙,或者用進(jìn)程表示。簡(jiǎn)單地講肠仪,文件存放數(shù)據(jù)或者允許訪問(wèn)資源肖抱,而進(jìn)程是正在執(zhí)行的程序。

在Unix中异旧,我們不談?wù)摮绦虻膱?zhí)行意述,而是談?wù)?strong>進(jìn)程(process)的執(zhí)行。進(jìn)程就是裝載到內(nèi)存中準(zhǔn)備運(yùn)行的程序吮蛹,以及程序的數(shù)據(jù)與跟蹤程序狀態(tài)所需的信息荤崇。進(jìn)程可以分成更小的單元,稱(chēng)為線程潮针,線程是一組運(yùn)行在進(jìn)行環(huán)境中的指令术荤。因此可以將程序的結(jié)構(gòu)描述為,在一個(gè)進(jìn)程之內(nèi)每篷,不止一個(gè)線程在同時(shí)運(yùn)行瓣戚。

所有的進(jìn)程都由內(nèi)核管理,內(nèi)核是操作系統(tǒng)的核心部分焦读。當(dāng)進(jìn)程創(chuàng)建時(shí)子库,內(nèi)核賦予其中一個(gè)唯一的標(biāo)識(shí)號(hào),為個(gè)標(biāo)識(shí)號(hào)稱(chēng)為進(jìn)程 IDPID 矗晃。為了跟蹤管理系統(tǒng)中的所有進(jìn)程仑嗅,內(nèi)核維護(hù)了一個(gè)進(jìn)程表。(在這點(diǎn)上,與文件的 i 節(jié)點(diǎn)號(hào)也挺相似的无畔。)

二啊楚、內(nèi)核管理進(jìn)程的方式

1、調(diào)度器 與 CPU 時(shí)間

小型的 Unix 系統(tǒng)很容易“同時(shí)”運(yùn)行 100 多個(gè)進(jìn)程浑彰。在大型系統(tǒng)中恭理,可能有數(shù)百個(gè)甚至數(shù)千個(gè)進(jìn)程,這些進(jìn)程都需要共享系統(tǒng)的資源:處理器郭变、內(nèi)存颜价、I/O 設(shè)備、網(wǎng)絡(luò)連接等诉濒。為了管理這樣一個(gè)復(fù)雜的工作負(fù)荷周伦,內(nèi)核提供了一個(gè)復(fù)雜的調(diào)度服務(wù),有時(shí)候稱(chēng)其為調(diào)度器(scheduler)未荒。

調(diào)度器一直維護(hù)一個(gè)所有正在等待執(zhí)行的進(jìn)程列表专挪。通過(guò)使用復(fù)雜的算法,調(diào)度器每次選擇一個(gè)進(jìn)程片排,給予這個(gè)進(jìn)程在一個(gè)短暫的時(shí)間間隔(稱(chēng)為時(shí)間片)中運(yùn)行的機(jī)會(huì)寨腔。

當(dāng)討論時(shí)間片概念時(shí),我們通常將處理時(shí)間稱(chēng)為 CPU 時(shí)間率寡。

一個(gè)典型的時(shí)間片通常是 10 毫秒的 CUP 時(shí)間迫卢。一旦時(shí)間片用用盡,該進(jìn)程將返回到調(diào)度列表冶共,由內(nèi)核啟動(dòng)另一個(gè)進(jìn)程乾蛤。通過(guò)這種方式,最終每個(gè)進(jìn)程都將獲得足夠的 CPU 時(shí)間來(lái)完成它們的工作捅僵。

2家卖、系統(tǒng)調(diào)用

內(nèi)核是操作系統(tǒng)的核心,因此命咐,內(nèi)核會(huì)為進(jìn)程提供一些基本的服務(wù)篡九,具體包括:

  • 內(nèi)存管理(虛擬內(nèi)存管理,包括分頁(yè))
  • 進(jìn)程管理(進(jìn)程創(chuàng)建醋奠、終止、調(diào)度)
  • 進(jìn)程間通信(本地伊佃、網(wǎng)絡(luò))
  • 輸入/輸出(通過(guò)設(shè)備驅(qū)動(dòng)程序窜司,即與物理設(shè)備實(shí)際通信的程序)
  • 文件管理
  • 安全和訪問(wèn)控制
  • 網(wǎng)絡(luò)管理(如 TCP/IP)

當(dāng)進(jìn)程需要執(zhí)行服務(wù)時(shí),它就使用系統(tǒng)調(diào)用發(fā)送請(qǐng)求航揉。例如塞祈,進(jìn)程使用系統(tǒng)調(diào)用初始化 I/O 操作。

許多重要的任務(wù)只能由內(nèi)核執(zhí)行帅涂。當(dāng)進(jìn)程需要執(zhí)行這樣的任務(wù)時(shí)议薪,進(jìn)程必須使用系統(tǒng)調(diào)用尤蛮,向內(nèi)核發(fā)送一個(gè)執(zhí)行任務(wù)的請(qǐng)求。Unix/Linux 系統(tǒng)通常有200-300個(gè)不同的系統(tǒng)系統(tǒng)調(diào)用斯议。最常用的系統(tǒng)調(diào)用是那些用于進(jìn)程控制(fork产捞、wait、exec哼御、exit和kill)和 文件 I/O(open坯临、read、write 和 close)的系統(tǒng)調(diào)用恋昼。

常用的系統(tǒng)調(diào)用:

系統(tǒng)調(diào)用 目的說(shuō)明
fork 創(chuàng)建當(dāng)前進(jìn)程的一個(gè)副本
wait 等待另一個(gè)進(jìn)程結(jié)束執(zhí)行
exec 在當(dāng)前進(jìn)程中執(zhí)行一個(gè)新的程序
exit 終止當(dāng)前進(jìn)程
kill 向另一個(gè)進(jìn)程發(fā)送一個(gè)信號(hào)
open 打開(kāi)一個(gè)用于讀取或?qū)懭氲奈募?/td>
read 從文件中讀取數(shù)據(jù)
write 向文件中寫(xiě)入數(shù)據(jù)
close 關(guān)閉文件

三看靠、父進(jìn)程與子進(jìn)程

1、概念

除了系統(tǒng)的初始化進(jìn)程(系統(tǒng)中所有進(jìn)程的父進(jìn)程)外液肌,Unix 中的每個(gè)進(jìn)程都是由另一個(gè)進(jìn)程創(chuàng)建挟炬。

fork 系統(tǒng)調(diào)用創(chuàng)建當(dāng)前進(jìn)程的一個(gè)副本。一旦發(fā)生這種情況嗦哆,我們稱(chēng)原始進(jìn)程為父進(jìn)程(parent process)辟宗。新進(jìn)程是和父進(jìn)程一模一樣的副本進(jìn)程氯哮,稱(chēng)為子進(jìn)程(child process)椒丧。

就以我們最熟悉的 shell 來(lái)說(shuō),shell 是一個(gè)充當(dāng)用戶(hù)界面和腳本解釋器的程序课蔬。但是烁峭,一旦 shell 開(kāi)始運(yùn)行容客,它只是眾多系統(tǒng)進(jìn)程中的一個(gè)。與所有進(jìn)程一樣约郁,shell 也擁有自己的進(jìn)程 ID(PID)缩挑,用如下方法可以方便地查看當(dāng)前 shell 的 PID:

[nosee@instance-4 ~]$ ps
  PID TTY          TIME CMD
10548 pts/0    00:00:00 bash
11440 pts/0    00:00:00 ps
[nosee@instance-4 ~]$ echo $$;
10548

當(dāng)在 shell 中輸入命令時(shí),我們把命令分為兩種類(lèi)型:內(nèi)部命令(內(nèi)置命令)和外部命令鬓梅。內(nèi)部命令直接由 shell 解釋?zhuān)虼瞬恍枰獎(jiǎng)?chuàng)建新進(jìn)程供置。但是,每當(dāng)運(yùn)行外部命令時(shí)绽快,shell 必須創(chuàng)建一個(gè)新進(jìn)程芥丧。

2、進(jìn)程分叉到死亡

為了創(chuàng)建一個(gè)新進(jìn)程坊罢,shell 所做的第一件事就是使用 fork 系統(tǒng)調(diào)用創(chuàng)建一個(gè)全新的進(jìn)程续担。原始進(jìn)程成為父進(jìn)程,而新進(jìn)程就成為子進(jìn)程活孩。

一旦進(jìn)程分叉(創(chuàng)建)成功物遇,就發(fā)生兩件事情:
首先,子進(jìn)程使用 exec 系統(tǒng)調(diào)用將它自身從運(yùn)行 shell 的進(jìn)程變成運(yùn)行外部程序的進(jìn)程。
其次询兴,父進(jìn)程使用 wait 系統(tǒng)調(diào)用暫停乃沙,直到子進(jìn)程結(jié)束執(zhí)行。

最終诗舰,外部程序結(jié)束警儒,此時(shí)子進(jìn)程使用 exit 系統(tǒng)調(diào)用停止自身。

每當(dāng)進(jìn)程永久停止時(shí)始衅,不管是由于什么原因停止冷蚂,我們都稱(chēng)進(jìn)程死亡(die)或者終止(terminate)。每當(dāng)進(jìn)程死亡時(shí)汛闸,進(jìn)程的所有資源(內(nèi)存蝙茶、文件等)都將被釋放,從而可以被其他進(jìn)程使用诸老。此時(shí)稱(chēng)殺死的進(jìn)程為僵進(jìn)程(zombie)隆夯。僵進(jìn)程已經(jīng)不再是一個(gè)真正的進(jìn)程,但是它仍然在進(jìn)程表中保留著自己的條目别伏。這是因?yàn)樵摋l目包含最近死亡的子進(jìn)程的數(shù)據(jù)蹄衷,而父進(jìn)程可能會(huì)需要這些數(shù)據(jù)。

在子進(jìn)程成為僵進(jìn)程后厘肮,父進(jìn)程(一直在等待子進(jìn)程死亡)立即被內(nèi)核喚醒±⒖冢現(xiàn)在父進(jìn)程有機(jī)會(huì)查看進(jìn)程表中的僵進(jìn)程條目,看看發(fā)生了什么結(jié)果类茂。然后內(nèi)核將進(jìn)程表中的僵進(jìn)程條目移除耍属。

3、第一個(gè)進(jìn)程:init

當(dāng)我們追蹤一個(gè)進(jìn)程的生成過(guò)程巩检,如果追蹤得足夠遠(yuǎn)厚骗,那么可以得到一個(gè)結(jié)論,即在某個(gè)地方兢哭,必定會(huì)有第一個(gè)進(jìn)程领舰。每個(gè) Unix 系統(tǒng)都擁有一個(gè)進(jìn)程(至少間接擁有)是系統(tǒng)中其它所有進(jìn)程的父進(jìn)程。

理解 Unix 的第一個(gè)進(jìn)程迟螺,需要從系統(tǒng)的啟動(dòng)開(kāi)始說(shuō)起冲秽。這里先理解一個(gè)思想:引導(dǎo)。

引導(dǎo)的思想就是一個(gè)困難的煮仇、復(fù)雜的目標(biāo)可以通過(guò)一個(gè)小的動(dòng)作開(kāi)始劳跃,然后以這個(gè)小動(dòng)作為基礎(chǔ),一步一步地到達(dá)期望目標(biāo)而完成浙垫。計(jì)算機(jī)系統(tǒng)就是以這種方式啟動(dòng)的:當(dāng)打開(kāi)計(jì)算機(jī)的電源時(shí),一個(gè)單獨(dú)的、小型的程序自動(dòng)運(yùn)行夹姥。這個(gè)程序啟動(dòng)另一個(gè)程序杉武,一個(gè)更復(fù)雜的程序,然后逐步遞進(jìn)辙售。最終轻抱,操作系統(tǒng)(一個(gè)非常復(fù)雜的程序)接過(guò)控制,完成初始化旦部。

在引導(dǎo)過(guò)程的末尾祈搜,內(nèi)核“手動(dòng)”創(chuàng)建一個(gè)特殊的進(jìn)程,而不是通過(guò)分叉士八。這個(gè)進(jìn)程的 PID為 0容燕。我們可以將它稱(chēng)為空閑進(jìn)程。在執(zhí)行一些重要的功能之后(如初始化內(nèi)核所需的數(shù)據(jù)結(jié)構(gòu))婚度,空閑進(jìn)程進(jìn)行分叉蘸秘,創(chuàng)建 #1 號(hào)進(jìn)程。然后空閑進(jìn)程執(zhí)行一個(gè)非常簡(jiǎn)單的程序蝗茁,該程序?qū)嵸|(zhì)上是一個(gè)無(wú)窮的循環(huán)醋虏,不做任何事(即進(jìn)入永久的休眠,這也是它命名的原因)哮翘。這里的思想就是颈嚼,每當(dāng)沒(méi)有進(jìn)程等待執(zhí)行時(shí),調(diào)度器就運(yùn)行空閑進(jìn)程饭寺。實(shí)際上阻课,如果使用 ps 命令顯示進(jìn)程 #0 的狀態(tài)時(shí),內(nèi)核會(huì)否認(rèn)該進(jìn)程的存在佩研。

接下來(lái)就是進(jìn)程 #1 了柑肴,進(jìn)程 #1 執(zhí)行設(shè)置內(nèi)核及結(jié)束引導(dǎo)過(guò)程所需的剩余步驟,所以我們稱(chēng)它為初始化進(jìn)程(init process)旬薯,并將該進(jìn)程的實(shí)際程序命名為 init 晰骑。具體而言,初始化進(jìn)程打開(kāi)系統(tǒng)控制臺(tái)绊序,掛載根文件系統(tǒng)硕舆,然后運(yùn)行包含在文件 /etc/inittab(不同系統(tǒng)可能不一樣,如 Debian 類(lèi)系統(tǒng)是 /etc/init.d)中的 shell 腳本骤公。這個(gè)過(guò)程中抚官,init 多次分叉,創(chuàng)建運(yùn)行系統(tǒng)所需的基本進(jìn)程阶捆,并允許用戶(hù)登錄凌节。在這一過(guò)程中钦听,init 成為系統(tǒng)中所有其他進(jìn)程的祖先。init 進(jìn)程永遠(yuǎn)不會(huì)停止倍奢,直到系統(tǒng)關(guān)閉朴上。

大多數(shù)的第三代進(jìn)程都是守護(hù)進(jìn)程,守護(hù)進(jìn)程的任務(wù)就是等待某些事情的發(fā)生卒煞,然后進(jìn)行適當(dāng)?shù)捻憫?yīng)痪宰。例如,有一些守護(hù)進(jìn)程不做其它事畔裕,專(zhuān)門(mén)等待用戶(hù)登錄衣撬。當(dāng)用戶(hù)準(zhǔn)備登錄時(shí)守護(hù)進(jìn)程就創(chuàng)建另一個(gè)進(jìn)程來(lái)處理這一任務(wù)。然后登錄守護(hù)進(jìn)程創(chuàng)建另一個(gè)進(jìn)程運(yùn)行用戶(hù)有 shell扮饶。最后具练,每當(dāng) shell 需要執(zhí)行用戶(hù)的程序時(shí),shell 就會(huì)妴另一個(gè)進(jìn)程來(lái)執(zhí)行任務(wù)贴届。

注:在 Debian 系統(tǒng)中靠粪,初始化進(jìn)程實(shí)際程序命名為 systemd,而不是 init毫蚓。

四占键、作業(yè)控制-介紹

1、概念

當(dāng)我們需要在后臺(tái)運(yùn)行一個(gè)進(jìn)程時(shí)元潘,可以在命令的末尾鍵入一個(gè)&字符以 異步進(jìn)程(asynchronous process)運(yùn)行該程序畔乙。異步進(jìn)程有兩個(gè)明確的特征:第一,默認(rèn)情況下翩概,標(biāo)準(zhǔn)輸入與空文件 /dev/null 相連牲距。第二,因?yàn)檫M(jìn)程自己運(yùn)行钥庇,不需要用戶(hù)輸入牍鞠,所以該進(jìn)程不響應(yīng) intr 和 quit 信號(hào)。所以评姨,如果異步進(jìn)程遇到了問(wèn)題难述,那么也不能使用^C鍵或者^\鍵來(lái)終止進(jìn)程,只能使用 kill 命令吐句。

為了能更加方便的管理后臺(tái)進(jìn)程胁后,很多 shell 都添加了一個(gè)新功能,即 作業(yè)控制嗦枢。

作業(yè)控制是一項(xiàng)由 shell 支持的特性攀芯,允許同時(shí)運(yùn)行多項(xiàng)作業(yè),其中一個(gè)作業(yè)在前臺(tái)運(yùn)行文虏,其他作業(yè)在后臺(tái)運(yùn)行侣诺。作業(yè)可以有選擇地掛起(暫停)殖演、重新啟動(dòng)、在前臺(tái)和后臺(tái)之間切換紧武,以及顯示狀態(tài)剃氧。

作業(yè)控制的本質(zhì)就是將每條輸入的命令視為一個(gè)作業(yè)敏储,該作業(yè)由唯一的 作業(yè)號(hào)(也稱(chēng) 作業(yè) ID)來(lái)標(biāo)識(shí)阻星。

2、作業(yè)控制相關(guān)工具

為了控制和管理作業(yè)已添,可以將作業(yè) ID 和一系列命令妥箕、變量、終端設(shè)置更舞、shell 變量 以及 shell 選項(xiàng) 一起使用畦幢。如下表,列舉了這些工具:

1)作業(yè)控制命令

命令 說(shuō)明
jobs 顯示作業(yè)列表
ps 顯示進(jìn)程列表
fg 將作業(yè)移至前臺(tái)
bg 將作業(yè)移至后臺(tái)
suspend 掛起當(dāng)前 shell
^Z 掛起當(dāng)前前臺(tái)作業(yè)
kill 向作業(yè)發(fā)送信號(hào)缆蝉;默認(rèn)情況下宇葱,終于作業(yè)

2)變量

變量 說(shuō)明
echo $$ 顯示當(dāng)前 shell 的 PID
echo $! 顯示上一條移至后臺(tái)的命令的 PID

3)終端設(shè)置

終端設(shè)置 說(shuō)明
stty tostop 掛起試圖向終端寫(xiě)數(shù)據(jù)的后臺(tái)作業(yè)
stty -tostop 關(guān)閉 tostop

4)shell 選項(xiàng)(bash shell)

shell 選項(xiàng) 說(shuō)明
set -o monitor 允許作業(yè)控制
set +o monitor 關(guān)閉 monitor
set -o notify 當(dāng)后臺(tái)作業(yè)結(jié)束時(shí)立即通知
set +o notify 關(guān)閉 notify

3、作業(yè)與進(jìn)程的區(qū)別

在很大程度上刊头,這兩個(gè)概念是相似的黍瞧,人們通常交換著使用術(shù)語(yǔ)“作業(yè)”和“進(jìn)程”。

但嚴(yán)格地講原杂,它們之間還是區(qū)別的印颤。

  • 進(jìn)程是正在執(zhí)行或者準(zhǔn)備執(zhí)行的程序,則作業(yè)是指解釋整個(gè)命令所需的全部進(jìn)程穿肄。
  • 進(jìn)程由內(nèi)核控制年局,而作業(yè)由 shell 控制。
  • 內(nèi)核使用進(jìn)程表記錄進(jìn)程咸产;而 shell 也采用相同的方式矢否,使用作業(yè)表記錄作業(yè)。

例如脑溢,當(dāng)輸出一個(gè)簡(jiǎn)單的命令date僵朗。該命令生成一個(gè)單獨(dú)的進(jìn)程(該進(jìn)程擁有自己的進(jìn)程 ID),和一個(gè)單獨(dú)的作業(yè)(該作業(yè)擁有自己的作業(yè) ID)焚志。在作業(yè)運(yùn)行時(shí)衣迷,進(jìn)程表會(huì)有一個(gè)新的條目,作業(yè)表也會(huì)有一個(gè)新的條目酱酬。

假如壶谒,是復(fù)雜一點(diǎn)的命令,如管道命令:who | cut -c 1-8 | sort | uniq -c膳沽。這條命令會(huì)生成 4 個(gè)不同的進(jìn)程汗菜,每個(gè)進(jìn)程都有自己的進(jìn)程 ID让禀。但是,整個(gè)管道線被認(rèn)為是一個(gè)單獨(dú)的作業(yè)陨界,擁有一個(gè)單獨(dú)的作業(yè) ID 巡揍。該作業(yè)運(yùn)行時(shí),進(jìn)程表中有 4 個(gè)條目菌瘪,但是作業(yè)表中只有一個(gè)條目腮敌。

五、作業(yè)控制-操作

1俏扩、在后臺(tái)運(yùn)行作業(yè):&

為了在后臺(tái)運(yùn)行作業(yè)糜工,需要在命令末鍵入一個(gè)&字符。

如:

[nosee@instance-4 ~]$ ls > aaa &
[1] 14836
[nosee@instance-4 ~]$

每次在后臺(tái)運(yùn)行作業(yè)時(shí)录淡,shell 都會(huì)顯示作業(yè)的作業(yè) ID 和進(jìn)程 ID捌木。shell 從 1 開(kāi)始為作業(yè)分配作業(yè) ID。而進(jìn)程 ID 由內(nèi)核分配嫉戚,大多時(shí)候是多位的數(shù)字刨裆。

當(dāng)后臺(tái)作業(yè)結(jié)束時(shí),shell 會(huì)給你發(fā)送一個(gè)簡(jiǎn)短的狀態(tài)消息彬檀。為了防止?fàn)顟B(tài)消息干擾另一個(gè)程序的輸出帆啃,shell 不會(huì)立即通知你。shell 會(huì)一直等待凤覆,直到要顯示下一個(gè) shell 提示链瓦,才給你發(fā)送通知。

如上面是一個(gè)簡(jiǎn)單的例子盯桦,現(xiàn)在肯定早就結(jié)束了慈俯,那我可以按回車(chē)鍵刷新一下 shell 提示就可以收到通知。

[nosee@instance-4 ~]$ ls > aaa &
[1] 14991
[nosee@instance-4 ~]$ 
[1]+  Done                    ls --color=auto > aaa
[nosee@instance-4 ~]$ 

或者我輸入一條新命令的時(shí)候拥峦,shell 就會(huì)在我新命令的輸出最后面通知我(也就是下一個(gè) shell 提示之前)贴膘,如下:

[nosee@instance-4 ~]$ ls > aaa &
[1] 14996
[nosee@instance-4 ~]$ pwd
/home/nosee
[1]+  Done                    ls --color=auto > aaa
[nosee@instance-4 ~]$ 

如果不希望等待,可以使用命令set -o notify來(lái)打開(kāi)即時(shí)通知略号。但是即時(shí)通知可能會(huì)干擾到你正在運(yùn)行的其他命令的輸出刑峡。

2、掛起作業(yè):^Z

在任何時(shí)候玄柠,每個(gè)作業(yè)都屬于 3 種狀態(tài)中的一種:前臺(tái)運(yùn)行突梦、后臺(tái)運(yùn)行、暫停羽利。

當(dāng)需要暫停前臺(tái)作業(yè)時(shí)宫患,可以按^Z鍵(Ctrl-Z)。這時(shí)發(fā)送 susp 信號(hào)这弧,從而使進(jìn)程暫停娃闲。當(dāng)通過(guò)這種方式暫停進(jìn)程時(shí)虚汛,我們稱(chēng)進(jìn)程 掛起(suspend),或者將進(jìn)程 停止(stop)皇帮。這里的停止是指臨時(shí)終止卷哩,一個(gè)停止的作業(yè)是還可以重新啟動(dòng)的。

如果希望永久的停止程序属拾,則必須按^C鍵或者使用 kill 命令将谊。

當(dāng)希望恢復(fù)掛起的程序時(shí),可以使用 fg 命令將該程序移回前臺(tái)捌年。

例如瓢娜,當(dāng)你使用vim aaa命令在編輯文件時(shí),突然想出去查看一下日期礼预。這時(shí)你可以按下^Z鍵回到 shell 界面,執(zhí)行你想執(zhí)行的命令date虏劲,然后你再使用fg命令回到你的 vim 編輯界面托酸。

[nosee@instance-4 ~]$ vim aaa 

[1]+  Stopped                 vim aaa
[nosee@instance-4 ~]$ date
Sun Jan 23 21:06:15 UTC 2022
[nosee@instance-4 ~]$ fg
vim aaa

上面的Stopped的意思就是該作業(yè)已經(jīng)被掛起。當(dāng)掛起作業(yè)時(shí)柒巫,如果你不做任何處理励堡,進(jìn)程會(huì)無(wú)限期的在等待。

3堡掏、掛起 shell:suspend

按下^Z鍵將掛起在前臺(tái)運(yùn)行的任何作業(yè)应结。但是有一個(gè)進(jìn)程不會(huì)掛起,這個(gè)進(jìn)程就是當(dāng)前 shell泉唁。如果希望掛起當(dāng)前 shell鹅龄,則需要使用suspend命令。(suspend - Suspend shell execution.)

例:

[nosee@instance-4 ~]$ su
Password: 
root@instance-4:/home/nosee# 
root@instance-4:/home/nosee# suspend 

[2]+  Stopped                 su
[nosee@instance-4 ~]$ 
[nosee@instance-4 ~]$ fg
su
root@instance-4:/home/nosee# 

默認(rèn)情況下亭畜,是不允許掛起登錄 shell 的扮休。如你在當(dāng)前 shell 以su -命令啟動(dòng)超級(jí)用戶(hù) shell 時(shí),將創(chuàng)建一個(gè)登錄 shell拴鸵。如果這種希望希望掛起這個(gè)新 shell 玷坠,則必須使用命令 suspend -f,帶-f選項(xiàng)表示強(qiáng)制掛起劲藐。如:

[nosee@instance-4 ~]$ su - 
Password: 
root@instance-4:~# suspend 
-bash: suspend: cannot suspend a login shell
root@instance-4:~# suspend -f

[3]+  Stopped                 su -
[nosee@instance-4 ~]$ 
[nosee@instance-4 ~]$ fg
su -
root@instance-4:~# 

注:命令su啟動(dòng)的是一個(gè)子 shell八堡,而命令su -是打開(kāi)一個(gè)新的登錄 shell。

4聘芜、顯示作業(yè)列表:jobs

在任何時(shí)候都可以使用 jobs 命令顯示所有作業(yè)的列表兄渺。(Display status of jobs.)

jobs 是一個(gè) shell 的內(nèi)置命令,可以使用help jobs去查看它的使用說(shuō)明厉膀。

例:

[nosee@instance-4 ~]$ jobs
[1]   Stopped                 vim aaa
[2]-  Stopped                 php -a
[3]+  Stopped                 vim letter.txt
  • 其中第一列的1溶耘、2二拐、3為作業(yè)的作業(yè) ID,后面的+表示“當(dāng)前作業(yè)”凳兵,-表示“前一個(gè)作業(yè)”百新。
  • 第二列中的Stopped表示這是掛起的作業(yè),如果是Running則表示后臺(tái)運(yùn)行中的作業(yè)庐扫。
  • 最后一列是該作業(yè)的命令.

如果希望同時(shí)查看對(duì)應(yīng)的進(jìn)程 ID饭望,則需要使用選項(xiàng)-l。如:

[nosee@instance-4 ~]$ jobs -l
[1]  15045 Stopped                 vim aaa
[2]- 15464 Stopped (tty input)     php -a
[3]+ 15465 Stopped                 vim letter.txt

5形庭、將作業(yè)移至前臺(tái):fg

fg - 將作業(yè)移至前臺(tái)铅辞。(Move job to the foreground)

語(yǔ)法:fg [job_spec]

fg 的語(yǔ)法非常靈活,不帶任何參數(shù)的話萨醒,則會(huì)作用于當(dāng)前作業(yè)斟珊,那作業(yè) ID 后面有一個(gè)+的那個(gè)。

將當(dāng)前作業(yè)移動(dòng)至前臺(tái)可以使用命令:fg富纸、fg +囤踩、fg %+%。這4個(gè)命令都是一樣的效果晓褪。

[nosee@instance-4 ~]$ jobs -l
[1]  15045 Stopped                 vim aaa
[2]- 15464 Stopped (tty input)     php -a
[3]+ 15465 Stopped                 vim letter.txt

例如堵漱,上面的3個(gè)作業(yè)中,如果我想把作業(yè) ID 為2的作業(yè)移至前臺(tái)涣仿,那我可以使用下列命令中的任何一條都可以:

%2
fg 2
fg -
fg %2
fg %-
fg %?php
fg %?-a

注:
fg命令是 shell 命令中唯一條命令名本身可選的命令勤庐。
即只輸入命令的參數(shù)就行,可以不輸入命令本身好港,如%2就相當(dāng)于fg %2愉镰。

6、將作業(yè)移至后臺(tái):bg

bg - 將作業(yè)移至后臺(tái)媚狰。(Move jobs to the background.)

在使用命令bg指定作業(yè)時(shí)岛杀,需要遵循和fg命令相同的規(guī)則。

命令bg的使用頻率要比命令fg少得多崭孤。但是有一種情況bg命令挺實(shí)用的:
就是當(dāng)準(zhǔn)備在后臺(tái)運(yùn)行時(shí)类嗤,但是忘記了在后面輸入&。這時(shí)只需按下^Z鍵掛起作業(yè)辨宠,然后用bg命令將作業(yè)移至后臺(tái)遗锣。

六、進(jìn)程查找-ps

1嗤形、ps 簡(jiǎn)介

ps 是一個(gè)功能強(qiáng)大的工具精偿,可以幫助查找特定的 PID(進(jìn)程 ID),檢查進(jìn)程正在做什么,并概述系統(tǒng)中正在發(fā)生的第一件事情笔咽。(report a snapshot of the current processes)

ps 擁有許多使人迷惑的選項(xiàng)搔预,這種情況主要是由于歷史的原因造成的。在很久以前叶组,Unix 有兩個(gè)主要的分支:UNIX 和 BSD拯田,它們都有自己的 ps 版本,每個(gè)版本都有自己的選項(xiàng)甩十。隨著時(shí)間的推移船庇,兩種類(lèi)型的 ps 都很出名,并且被廣泛使用侣监。

最終的結(jié)果是鸭轮,許多現(xiàn)代版本的 ps 同時(shí)支持兩種類(lèi)型的選項(xiàng),即所謂的 Unix 選項(xiàng)和 BSD 選項(xiàng)橄霉。

查看 ps 的 man 手冊(cè)如下窃爷,發(fā)現(xiàn)還有一種 GNU 系統(tǒng)的選項(xiàng),但是基本上用不著酪劫,所以這里就不討論了吞鸭。

This version of ps accepts several kinds of options:
       1   UNIX options, which may be grouped and must be preceded by a dash.
       2   BSD options, which may be grouped and must not be used with a dash.
       3   GNU long options, which are preceded by two dashes.

對(duì)于 ps 的選項(xiàng)來(lái)說(shuō),有一個(gè)有趣的傳統(tǒng):Unix 選項(xiàng)通常以連字符-開(kāi)頭覆糟,而 BSD 選項(xiàng)前面沒(méi)有連字符。

ps 命令較簡(jiǎn)單的語(yǔ)法格式為:
使用 Unix 選項(xiàng):ps [-aefFly] [-p pid] [-u userid]
使用 BSD 選項(xiàng):ps [ajluvx] [p pid] [U userid]

默認(rèn)情況下遮咖,ps 不會(huì)顯示很多進(jìn)程信息滩字,只是列出與當(dāng)前終端會(huì)話相關(guān)的進(jìn)程。

[nosee@instance-4 ~]$ ps
  PID TTY          TIME CMD
10548 pts/0    00:00:00 bash
15464 pts/0    00:00:00 php
15757 pts/0    00:00:00 vim
20359 pts/0    00:00:00 ps

盡管 ps 擁有許多的選項(xiàng)御吞,但是日常工作僅需要少數(shù)幾個(gè)選項(xiàng)麦箍。

2、常用選項(xiàng)

1)Unix 選項(xiàng)

顯示哪些進(jìn)程: ——
ps 與 你的用戶(hù)標(biāo)識(shí)和終端 相關(guān)的進(jìn)程
ps -a 與 任何用戶(hù)標(biāo)識(shí)和終端 相關(guān)的進(jìn)程(except session leaders)
ps -e 所有進(jìn)程(包括守護(hù)進(jìn)程)
ps -p pid 與指定進(jìn)程 ID pid 相關(guān)的進(jìn)程
ps -u userid 與打指定用戶(hù)標(biāo)識(shí) userid 相關(guān)的進(jìn)程
顯示哪些數(shù)據(jù)列: ——
ps PID TTY TIME CMD
ps -f UID PID PPID C STIME TTY TIME CMD
ps -F UID PID PPID C SZ RSS PSR STIME TTY TIME CMD
ps -l F S UID PID PPID C PRI NI ADDR SZ WCHSN TTY TIME CMD
ps -ly S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
有用的特殊組合: ——
ps 顯示自己的進(jìn)程
ps -ef 顯示所有用戶(hù)進(jìn)程陶珠,完整輸出
ps -a 顯示所有非守護(hù)進(jìn)程的進(jìn)程
ps -t - 僅顯示所有守護(hù)進(jìn)程

例:查看系統(tǒng)上的所有進(jìn)程

To see every process on the system using standard syntax:
    ps -e
    ps -ef
    ps -eF
    ps -ely

例:顯示進(jìn)程樹(shù)(選項(xiàng):-H

To print a process tree:
    ps -ejH

2)BSD 選項(xiàng)

顯示哪些進(jìn)程: ——
ps 與你的用戶(hù)標(biāo)識(shí)和終端相關(guān)的進(jìn)程
ps a 與任何用戶(hù)標(biāo)識(shí)和終端相關(guān)的進(jìn)程
ps e 所有進(jìn)程(包括守護(hù)進(jìn)程)
ps p pid 與指定進(jìn)程 ID pid 相關(guān)的進(jìn)程
ps U userid 與打指定用戶(hù)標(biāo)識(shí) userid 相關(guān)的進(jìn)程
顯示哪些數(shù)據(jù)列: ——
ps PID TTY TIME CMD
ps j PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
ps l F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
ps u USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
ps v PID TTY STAT TIME MAJFL TRS DRS RSS %MEM COMMAND
有用的特殊組合: ——
ps 顯示自己的進(jìn)程
ps ax 顯示所有進(jìn)程
ps aux 顯示所有進(jìn)程挟裂,完整輸出

例:查看系統(tǒng)上的所有進(jìn)程

To see every process on the system using BSD syntax:
    ps ax
    ps axu

例:顯示進(jìn)程樹(shù)(選項(xiàng):f

To print a process tree:
    ps axjf

3、常見(jiàn)的數(shù)據(jù)列

1)Unix 選項(xiàng)

列標(biāo)題 含義
ADDR 進(jìn)程列中的虛擬地址
CMD 正被執(zhí)行的命令名稱(chēng)
F 與進(jìn)程相關(guān)的標(biāo)志
NI nice 值揍诽,用于設(shè)置優(yōu)先級(jí)
PID 進(jìn)程 ID
PPID 父進(jìn)程 ID
PRI 優(yōu)先級(jí)(較大的數(shù)字=較低的優(yōu)先級(jí))
RSS 內(nèi)存駐留空間大芯魅亍(內(nèi)存和管理)
S 狀態(tài)代碼:D(不可中斷睡眠)、R(正在運(yùn)行可可運(yùn)行)暑脆、S(可中斷睡眠)渠啤、T(掛起)、Z(僵進(jìn)程)
STIME 累積系統(tǒng)時(shí)間
SZ 物理頁(yè)的大刑砺稹(內(nèi)存管理)
TIME 累積CPU時(shí)間
TTY 控制終端的名稱(chēng)
UID 用戶(hù) ID
WCHAN 等待通道

2)BSD 選項(xiàng)

列標(biāo)題 含義
%CPU CPU(處理器)使用百分比
%MEM 真實(shí)內(nèi)存使用百分比
CMD 正被執(zhí)行的命令的名稱(chēng)
COMMAND 正被執(zhí)行的命令的完整名稱(chēng)
NI nice 值沥曹,用于設(shè)置優(yōu)先級(jí)
PGID 進(jìn)程組號(hào)
PID 進(jìn)程 ID
PPID 父進(jìn)程 ID
PRI 調(diào)度優(yōu)先級(jí)
RSS 內(nèi)存駐留空間大小(內(nèi)存管理)
STAT 狀態(tài)代碼:O(正在運(yùn)行)、R(運(yùn)行)妓美、S(正在睡眠)僵腺、T(掛起)、Z(僵進(jìn)程)
TIME 累積 CPU 時(shí)間
TTY 控制終端的名稱(chēng)
UID 用戶(hù) ID
USER 用戶(hù)標(biāo)識(shí)
VSZ 虛擬大泻啊(單位:KB)
WCHAN 等待通道

4辰如、嘗試追蹤一個(gè)進(jìn)程的父進(jìn)程 ID

[nosee@instance-4 ~]$ ps -aj
  PID  PGID   SID TTY          TIME CMD
15464 15464 10548 pts/0    00:00:00 php
15757 15757 10548 pts/0    00:00:00 vim
19054 19054 18901 pts/1    00:00:00 vim
19766 19766 10548 pts/0    00:00:00 ps
[nosee@instance-4 ~]$ ps -fp 15464
UID        PID  PPID  C STIME TTY          TIME CMD
nosee    15464 10548  0 Jan23 pts/0    00:00:00 php -a
[nosee@instance-4 ~]$ ps -fp 10548
UID        PID  PPID  C STIME TTY          TIME CMD
nosee    10548 10547  0 Jan23 pts/0    00:00:00 -bash
[nosee@instance-4 ~]$ ps -fp 10547
UID        PID  PPID  C STIME TTY          TIME CMD
nosee    10547 10529  0 Jan23 ?        00:00:00 sshd: nosee@pts/0
[nosee@instance-4 ~]$ ps -fp 10529
UID        PID  PPID  C STIME TTY          TIME CMD
root     10529   585  0 Jan23 ?        00:00:00 sshd: nosee [priv]
[nosee@instance-4 ~]$ ps -fp 585
UID        PID  PPID  C STIME TTY          TIME CMD
root       585     1  0 Jan22 ?        00:00:01 /usr/sbin/sshd -D
[nosee@instance-4 ~]$ ps -fp 1
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 Jan22 ?        00:00:06 /sbin/init

注:
1)如我們前面介紹的,追蹤父進(jìn)程最終總會(huì)回到初始化進(jìn)程(init process)—— 所有進(jìn)程的父進(jìn)程委刘。
2)TTY 列中的?(問(wèn)號(hào))表示該進(jìn)程沒(méi)有控制終端丧没,我們稱(chēng)這樣的進(jìn)程為“守護(hù)進(jìn)程”。

5锡移、查找指定名稱(chēng)的進(jìn)程

1) ps -ef | grep 名稱(chēng)

[nosee@instance-4 ~]$ ps -ef | grep php
root       412     1  0 21:11 ?        00:00:00 php-fpm: master process (/etc/php/7.3/fpm/php-fpm.conf)
www-data   522   412  0 21:11 ?        00:00:00 php-fpm: pool www
www-data   523   412  0 21:11 ?        00:00:00 php-fpm: pool www
nosee     1635  1237  0 21:41 pts/0    00:00:00 grep --color php
[nosee@instance-4 ~]$ ps -ef | grep mysql
mysql      515     1  0 21:11 ?        00:00:03 /usr/sbin/mysqld
nosee     1641  1237  0 21:41 pts/0    00:00:00 grep --color mysql
[nosee@instance-4 ~]$ ps -ef | grep nginx
root       449     1  0 21:11 ?        00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data   451   449  0 21:11 ?        00:00:00 nginx: worker process
www-data   452   449  0 21:11 ?        00:00:00 nginx: worker process
nosee     1697  1237  0 21:46 pts/0    00:00:00 grep --color nginx

2) ps aux | grep 名稱(chēng)

[nosee@instance-4 ~]$ ps axu | grep php
root       412  0.0  0.5 196232 21428 ?        Ss   21:11   0:00 php-fpm: master process (/etc/php/7.3/fpm/php-fpm.conf)
www-data   522  0.0  0.1 196232  7568 ?        S    21:11   0:00 php-fpm: pool www
www-data   523  0.0  0.1 196232  7568 ?        S    21:11   0:00 php-fpm: pool www
nosee     1621  0.0  0.0   4836   820 pts/0    R+   21:40   0:00 grep --color php
[nosee@instance-4 ~]$ ps axu | grep mysql
mysql      515  0.1  9.8 1738588 398980 ?      Ssl  21:11   0:03 /usr/sbin/mysqld
nosee     1623  0.0  0.0   4836   884 pts/0    S+   21:41   0:00 grep --color mysql
[nosee@instance-4 ~]$ ps aux | grep nginx
root       449  0.0  0.0  65660  1728 ?        Ss   21:11   0:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data   451  0.0  0.0  66008  3440 ?        S    21:11   0:00 nginx: worker process
www-data   452  0.0  0.0  66008  3440 ?        S    21:11   0:00 nginx: worker process
nosee     1705  0.0  0.0   4836   824 pts/0    R+   21:46   0:00 grep --color nginx

3)如果想要同時(shí)顯示出列的名稱(chēng)呕童,可以這樣:

[nosee@instance-4 ~]$ ps -ef | grep -E 'php|UID'
UID        PID  PPID  C STIME TTY          TIME CMD
root       412     1  0 21:11 ?        00:00:00 php-fpm: master process (/etc/php/7.3/fpm/php-fpm.conf)
www-data   522   412  0 21:11 ?        00:00:00 php-fpm: pool www
www-data   523   412  0 21:11 ?        00:00:00 php-fpm: pool www
nosee     1949  1237  0 21:56 pts/0    00:00:00 grep --color -E php|UID

4)用pgrep根據(jù)進(jìn)程名查找相關(guān)進(jìn)程信息

  • 先用pgrep [str] 命令進(jìn)行模糊匹配,找到匹配該特征串的進(jìn)程ID淆珊;
  • 其次根據(jù)進(jìn)程ID顯示指定的進(jìn)程信息夺饲,ps --pid [pid];

如查詢(xún)mysql的進(jìn)程信息:

root@Chan:~# pgrep mysql
914
root@Chan:~# ps -p 914
  PID TTY          TIME CMD
  914 ?        00:01:32 mysqld    ## “CMD”欄則顯示了線程名稱(chēng)
root@Chan:~# ps -u -p 914    ## 加上-u參數(shù)施符,可以顯示進(jìn)程詳細(xì)信息
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
mysql      914  0.0 11.9 1107652 121424 ?      Ssl  Nov30   1:32 /usr/sbin/mysqld
root@Chan:~# ps -T -p 914    ## 在ps命令中往声,"-T"選項(xiàng)可以開(kāi)啟線程查看。
  PID  SPID TTY          TIME CMD
  914   914 ?        00:00:00 mysqld
  914  1094 ?        00:00:00 mysqld
  914  1099 ?        00:00:04 mysqld
  914  1100 ?        00:00:04 mysqld
...
  914  1136 ?        00:00:00 mysqld
  914  1137 ?        00:00:00 mysqld

七戳吝、進(jìn)程管理

1浩销、監(jiān)視系統(tǒng)進(jìn)程:top

為了查看指定的進(jìn)程,可以使用 ps 命令听哭。但是慢洋,ps 只顯示進(jìn)程的靜態(tài)快照普筹,即瞬間的進(jìn)程狀態(tài)太防。

進(jìn)程是動(dòng)態(tài)的酸员,不斷變化的。如果希望查看系統(tǒng)的整體運(yùn)行情況醇王,可以使用 top 程序每隔幾秒鐘顯示整個(gè)系統(tǒng)的統(tǒng)計(jì)更新寓娩,并實(shí)時(shí)顯示最重要的進(jìn)程的信息。(display Linux processes)

top 程序用來(lái)顯示系統(tǒng)上“頂端”進(jìn)程的動(dòng)態(tài)信息棘伴,也就是使用最多 CPU 時(shí)間的進(jìn)程寞埠。

語(yǔ)法:top -hv|-bcEHiOSs1 -d secs -n max -u|U user -p pid -o fld -w [cols]

常用選項(xiàng):

  • -d secs,刷新間隔焊夸,單位為秒仁连。(默認(rèn)3秒,不同系統(tǒng)可能會(huì)不一樣)
  • -n max阱穗,刷新的總次數(shù)饭冬,單位:次。
  • -p pid揪阶,進(jìn)程 ID昌抠,多個(gè)進(jìn)程 ID 可以用逗號(hào)分開(kāi)。

例:直接輸入命令top

top - 05:19:43 up 1 day, 16:19,  2 users,  load average: 0.00, 0.07, 0.09
Tasks:  87 total,   1 running,  84 sleeping,   2 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   3946.1 total,   2847.0 free,    523.4 used,    575.8 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   3147.3 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
  408 root      20   0  196232  21696  16152 S   0.3   0.5   0:05.76 php-fpm7.3     
  506 mysql     20   0 1739756 397508  33584 S   0.3   9.8   3:07.49 mysqld 
20323 nosee     20   0    9928   3596   3016 R   0.3   0.1   0:00.32 top   
    1 root      20   0  169664  10252   7788 S   0.0   0.3   0:06.87 systemd       
    2 root      20   0       0      0      0 S   0.0   0.0   0:00.00 kthreadd
    3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp
    4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_par_gp      
    6 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker/0:0H-kblockd
    8 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 mm_percpu_wq 
    9 root      20   0       0      0      0 S   0.0   0.0   0:00.10 ksoftirqd/0 

1)top 信息說(shuō)明:

  • 最前面的5行(系統(tǒng)整體的統(tǒng)計(jì)信息)
信息 說(shuō)明
第一行 ——與uptime命令輸出的結(jié)果相同——
top - 05:19:43 當(dāng)前系統(tǒng)時(shí)間
up 1 day, 16:19 系統(tǒng)運(yùn)行總時(shí)間(從開(kāi)機(jī)到現(xiàn)在)
2 users 當(dāng)前登錄用戶(hù)數(shù)量
load average: 0.00, 0.07, 0.09 CPU 的平均負(fù)載情況鲁僚,三個(gè)數(shù)值分別為 1分鐘炊苫、5分鐘、15分鐘前到現(xiàn)在的平均值冰沙。
理想值:?jiǎn)魏?CPU 情況(0.7), 多核 CPU 情況(CPU 核數(shù) * 0.7)
一般侨艾,當(dāng)系統(tǒng)負(fù)載 > CPU 核數(shù) * 0.7 時(shí),就需要進(jìn)行一定的優(yōu)化處理了
第二行:Tasks ——總結(jié)了進(jìn)程數(shù)目和各種進(jìn)程狀態(tài)——
total拓挥、running唠梨、sleeping、
stopped姻成、zombie
進(jìn)程總數(shù)糠雨、正在運(yùn)行的進(jìn)程數(shù)、睡眠的進(jìn)程數(shù)松邪、停止的進(jìn)程數(shù)、僵尸進(jìn)程數(shù)
第三行:%Cpu(s) ——描述了 CPU 正在執(zhí)行的進(jìn)程的特性——
us:運(yùn)行(未調(diào)整優(yōu)先級(jí)的)用戶(hù)進(jìn)程的 CPU 時(shí)間
sy:運(yùn)行內(nèi)核進(jìn)程的 CPU 時(shí)間
ni:行已調(diào)整優(yōu)先級(jí)的用戶(hù)進(jìn)程的 CPU 時(shí)間
id:CPU 空閑時(shí)間百分比
wa:用于等待 IO 完成的 CPU 時(shí)間
hi:處理硬件中斷的 CPU 時(shí)間
si:處理軟件中斷的 CPU 時(shí)間
st:Steal time 虛擬機(jī)被hypervisor 偷去的 CPU 時(shí)間
第四行:MiB Mem ————物理內(nèi)存的使用情況————
total、free褂傀、used同波、buff/cache 物理內(nèi)存總量未檩、空閑內(nèi)存、已使用的物理內(nèi)存筒溃、用作內(nèi)核緩存的內(nèi)存量
第五行:MiB Swap ————虛擬內(nèi)存的使用情況————
total、free、used滥崩、avail Mem 交換區(qū)總量、空閑交換區(qū)短条、已使用的交換區(qū)、可用于進(jìn)程下一次分配的物理內(nèi)存數(shù)量
  • 空白行下面(各個(gè)進(jìn)程的數(shù)據(jù)可都,每行描述一個(gè)進(jìn)程命斧。以 CPU 的使用率排序)
說(shuō)明
PID 進(jìn)程 ID
USER 進(jìn)程所有者的用戶(hù)標(biāo)識(shí)
PR 進(jìn)程的優(yōu)先級(jí)
NI nice 值。負(fù)值表示高優(yōu)先級(jí)汇四,正值表示低優(yōu)先級(jí)
VIRT 進(jìn)程使用的虛擬內(nèi)存總量,單位 KB背苦。VIRT=SWAP+RES
RES 常駐內(nèi)存。進(jìn)程使用的厚宰、未被換出的物理內(nèi)存大小,單位 KB撵幽。RES=CODE+DATA
SHR 共享內(nèi)存大小,單位 KB
S 程狀態(tài)。D=不可中斷的睡眠狀態(tài),R=運(yùn)行,S=睡眠,T=跟蹤/停止,Z=僵尸進(jìn)程
%CPU 自從上一次更新時(shí)到現(xiàn)在任務(wù)所使用的 CPU 時(shí)間百分比
%MEM 進(jìn)程使用的可用物理內(nèi)存百分比
TIME+ 任務(wù)啟動(dòng)后到現(xiàn)在所使用的全部 CPU 時(shí)間更耻,精確到百分之一秒
PPID 父進(jìn)程 ID
UID 進(jìn)程所有者的用戶(hù) ID
TTY 動(dòng)進(jìn)程的終端名食侮。不是從終端啟動(dòng)的進(jìn)程則顯示為“?”
SWAP 進(jìn)程使用的虛擬內(nèi)存中,被換出的大小眉尸,單位 KB
TIME 進(jìn)程使用的 CPU 時(shí)間總計(jì),單位秒
COMMAND 運(yùn)行進(jìn)程所使用的命令袱蜡。進(jìn)程名稱(chēng)(命令名/命令行)

2)top 操作(交互)

與 less 和 vim 相似,top 也是以原始模式工作(完全接管命令行和屏幕)敏晤。

常用按鍵(交互) 說(shuō)明
1(數(shù)字1) 顯示 CPU 詳細(xì)信息,每核顯示一行
d seconds、s seconds 修改刷新頻率扶平,單位(秒)
f 進(jìn)入另一個(gè)界面,編輯視圖中的顯示字段麻献,還可以改變字段的位置
h、? 顯示幫助信息
k pid 終止一個(gè)進(jìn)程( pid 為進(jìn)程 ID)
n number 指定進(jìn)程列表顯示行數(shù):number齿桃,默認(rèn)為滿(mǎn)屏行數(shù)
u username 輸入用戶(hù)標(biāo)識(shí)带污,顯示用戶(hù)標(biāo)識(shí)相關(guān)的任務(wù)
q、^C 退出 top 程序
l(小寫(xiě)L) 隱藏/顯示 第 1 行負(fù)載信息
t 隱藏/切換 第 2~3 行 CPU 信息
m 隱藏/切換 第 4~5 行內(nèi)存信息
H 顯示線程(把第二行的 Tasks 信息切換為 Threads 信息)
M 根據(jù)使用物理內(nèi)存百分比(%MEM)進(jìn)行排序
P(大寫(xiě)P) 根據(jù) CPU 占用時(shí)間(%CPU)進(jìn)行排序
T 根據(jù)時(shí)間/累計(jì)時(shí)間(TIME+)進(jìn)行排序
R 切換排序順序:正常排序/反向排序雷绢;
b 打開(kāi)/關(guān)閉 加亮效果
x 打開(kāi)/關(guān)閉 排序列的加亮效果(打開(kāi)后可以通過(guò)Shift+>Shift+<按鍵來(lái)改變排序列)
y 打開(kāi)/關(guān)閉 運(yùn)行態(tài)進(jìn)程的加亮效果
z 改變顏色

2、顯示進(jìn)程樹(shù):pstree

1)概念

pstree 是一個(gè)對(duì)于理解進(jìn)程之間的關(guān)系非常有用的工具。

前面我們已經(jīng)了解踪宠,每個(gè)進(jìn)程(除了第一個(gè))都有一個(gè)父進(jìn)程。因此柬脸,可以這樣假設(shè),即系統(tǒng)中的所有進(jìn)程都被安排到一個(gè)大型的樹(shù)型結(jié)構(gòu)中垦巴,而初始進(jìn)程位于樹(shù)的根部。我們稱(chēng)這樣的數(shù)據(jù)結(jié)構(gòu)為進(jìn)程樹(shù)(process tree)涯雅,并使用它們來(lái)表示父進(jìn)程及其子孫之間的連接。

pstree 程序可以用來(lái)顯示系統(tǒng)進(jìn)程樹(shù)的任何部分蔗候。例如,從初始化進(jìn)程開(kāi)始顯示整個(gè)進(jìn)程樹(shù)所灸,或者基于特定的 PID 或者用戶(hù)標(biāo)識(shí)顯示一個(gè)子樹(shù)。(display a tree of processes)

2)最簡(jiǎn)單的例子

默認(rèn)情況下侠驯,pstree 從初始化進(jìn)程開(kāi)始,繪制整個(gè)進(jìn)程樹(shù)檩坚。

[nosee@instance-4 ~]$ pstree
systemd─┬─2*[agetty]
        ├─apache2───6*[apache2]
        ├─chronyd───chronyd
        ├─cron
        ├─dbus-daemon
        ├─dhclient
        ├─google_guest_ag───11*[{google_guest_ag}]
        ├─google_osconfig───9*[{google_osconfig}]
        ├─haveged
        ├─mysqld───37*[{mysqld}]
        ├─php-fpm7.3───2*[php-fpm7.3]
        ├─rsyslogd───3*[{rsyslogd}]
        ├─sshd───sshd───sshd───bash───pstree
        ├─systemd───(sd-pam)
        ├─systemd-journal
        ├─systemd-logind
        ├─systemd-udevd
        └─unattended-upgr

注意上面例子的n*表示法,意味著n個(gè)完全相同的子樹(shù)(子進(jìn)程)剩檀。

注:在 Debian 系統(tǒng)中,初始化進(jìn)程名稱(chēng)為 systemd运嗜,而不是 init。

3)語(yǔ)法選項(xiàng)

語(yǔ)法:pstree [options] [pid|user]

  • -a抵怎,顯示每個(gè)進(jìn)程的整個(gè)命令行尝艘,而不只是程序的名稱(chēng)秒际。
  • -c娄徊,不壓縮相同的子樹(shù)(子進(jìn)程)。
  • -n锐峭,按 PID 進(jìn)行排序(默認(rèn)情況,在進(jìn)程樹(shù)中同一層是根據(jù)進(jìn)程名稱(chēng)排序)。
  • -p具温,顯示每個(gè)進(jìn)程的 PID揖铜。
  • -u,當(dāng)子進(jìn)程以不同于父進(jìn)程的用戶(hù)標(biāo)識(shí)運(yùn)行時(shí)龄寞,顯示出子進(jìn)程的用戶(hù)標(biāo)識(shí)
  • -A,使用純 ASCII 字符繪制樹(shù)的分支茂嗓。
  • -G在抛,使用特殊行繪制字符(默認(rèn))肠阱。

例:指定用戶(hù)標(biāo)識(shí)

[nosee@instance-4 ~]$ pstree -pa nosee
sshd,768   
  └─bash,769
      ├─pstree,987 -pa nosee
      └─vim,911 letter.txt

systemd,754 --user
  └─(sd-pam),755

例:指定 PID

[nosee@instance-4 ~]$ pstree -pa 769
bash,769
  ├─pstree,946 -pa 769
  └─vim,911 letter.txt

3走趋、向進(jìn)程發(fā)送信號(hào):kill

kill 程序有兩種應(yīng)用:終于程序,以及向程序發(fā)送信號(hào)姨伟。(send a signal to a process)

1)終止程序(kill 與 kill -9)

語(yǔ)法:kill [-9] [pid...|%jobid...]

例:默認(rèn)不帶選項(xiàng)

[07:01 @nosee ~/Desktop]$ jobs -l
[1]+  5273 Stopped                 vi test1
[07:02 @nosee ~/Desktop]$ kill 5273
[07:02 @nosee ~/Desktop]$ jobs -l
[1]+  5273 Stopped                 vi test1
[07:02 @nosee ~/Desktop]$ fg %1
vi test1
Vim: Caught deadly signal TERM
                              Vim: Finished.
Terminated
[07:03 @nosee ~/Desktop]$ jobs -l
[07:03 @nosee ~/Desktop]$ 

從上面可以發(fā)現(xiàn),當(dāng)使用命令kill 5273去殺死一個(gè)進(jìn)程時(shí),這個(gè)進(jìn)程并沒(méi)有立即消失嫩痰。當(dāng)我想把該作業(yè)移至前臺(tái)才發(fā)現(xiàn)它已經(jīng)被殺死了。(后面解釋原因)

例:使用選項(xiàng)-9

[nosee@instance-4 ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
nosee     1237  1236  0 21:28 pts/0    00:00:00 -bash
nosee     2542  1237  0 22:28 pts/0    00:00:00 less letter.txt
nosee     2630  1237  0 22:31 pts/0    00:00:00 ps -f
[nosee@instance-4 ~]$ kill -9 2542
[nosee@instance-4 ~]$ ps -f
UID        PID  PPID  C STIME TTY          TIME CMD
nosee     1237  1236  0 21:28 pts/0    00:00:00 -bash
nosee     2631  1237  0 22:32 pts/0    00:00:00 ps -f

當(dāng)使用 kill 程序來(lái)終止進(jìn)程時(shí)魔招,我們也稱(chēng)為殺死了該進(jìn)程。

例:殺死一個(gè)作業(yè)

[nosee@instance-4 ~]$ jobs -l
[1]+  2685 Stopped                 vim letter.txt
[nosee@instance-4 ~]$ kill -9 %1

[1]+  Stopped                 vim letter.txt
[nosee@instance-4 ~]$ 
[1]+  Killed                  vim letter.txt

使用-9選項(xiàng)會(huì)發(fā)送一個(gè)“強(qiáng)制殺死”的信號(hào)鳞疲,一般這是殺死一個(gè)進(jìn)程最后的選擇,因?yàn)樗鼩⑺肋M(jìn)程的過(guò)程非常快潮酒。使用kill -9殺死進(jìn)程時(shí),并不允許進(jìn)程釋放正在使用的資源勃教。例如,進(jìn)程可能沒(méi)有關(guān)閉文件(可能導(dǎo)致數(shù)據(jù)丟失)心软、沒(méi)有釋放內(nèi)存等。還可能導(dǎo)致產(chǎn)生不受約束的子進(jìn)程(這種進(jìn)程不能正確死亡)。

盡管內(nèi)核通常會(huì)清理這種混亂,但是在使用kill -9最好先嘗試其它的方法逐纬。

2)kill 與 kill -9 的區(qū)別

kill 命令默認(rèn)的信號(hào)就是15兔毒,也就是kill -15,被稱(chēng)為優(yōu)雅的退出豪嗽。
當(dāng)使用kill -15時(shí)窃躲,系統(tǒng)會(huì)發(fā)送一個(gè)SIGTERM的信號(hào)給對(duì)應(yīng)的程序赎婚。當(dāng)程序接收到該信號(hào)后刘绣,具體要如何處理是自己可以決定的。

這時(shí)候挣输,應(yīng)用程序可以選擇:
-- 立即停止程序
-- 釋放響應(yīng)資源后停止程序
-- 忽略該信號(hào)纬凤,繼續(xù)執(zhí)行程序

因?yàn)?code>kill -15信號(hào)只是通知對(duì)應(yīng)的進(jìn)程要進(jìn)行"安全、干凈的退出"撩嚼,程序接到信號(hào)之后停士,退出前一般會(huì)進(jìn)行一些"準(zhǔn)備工作"蜻底,如資源釋放、臨時(shí)文件清理等等谁尸,如果準(zhǔn)備工作做完了,再進(jìn)行程序的終止蠢棱。但是,如果在"準(zhǔn)備工作"進(jìn)行過(guò)程中刺下,遇到阻塞或者其他問(wèn)題導(dǎo)致無(wú)法成功构挤,那么應(yīng)用程序可以選擇忽略該終止信號(hào)呀邢。

這也就是為什么我們有的時(shí)候使用 kill 命令是沒(méi)辦法"殺死"應(yīng)用的原因病毡,因?yàn)槟J(rèn)的 kill 信號(hào)是SIGTERM(15),而SIGTERM(15)的信號(hào)是可以被阻塞和忽略的伤塌。

kill -15相比童本,kill -9就相對(duì)強(qiáng)硬一點(diǎn),系統(tǒng)會(huì)發(fā)出SIGKILL信號(hào),他要求接收到該信號(hào)的程序應(yīng)該立即結(jié)束運(yùn)行幸斥,不能被阻塞或者忽略,可以稱(chēng)為必殺命令。

所以,相比于kill -15命令,kill -9在執(zhí)行時(shí)烦磁,應(yīng)用程序是沒(méi)有時(shí)間進(jìn)行"準(zhǔn)備工作"的撮躁,所以這通常會(huì)帶來(lái)一些副作用胧砰,數(shù)據(jù)丟失或者終端無(wú)法恢復(fù)到正常狀態(tài)等。

3)向程序發(fā)送的信號(hào)

kill 程序的目的就是支持一種不同類(lèi)型的 IPC(進(jìn)程間通信)私恬,具體而言宁否,就是發(fā)送一個(gè)非常簡(jiǎn)單的消息,這種消息稱(chēng)為信號(hào)堂飞。信號(hào)只不過(guò)是發(fā)送給進(jìn)程的一個(gè)數(shù)字,從而讓進(jìn)程知道發(fā)生了哪些類(lèi)型的事。進(jìn)程會(huì)識(shí)別信號(hào)睁蕾,從而決定執(zhí)行什么動(dòng)作,當(dāng)進(jìn)程這樣做時(shí)我們稱(chēng)進(jìn)程捕獲了信號(hào)敢辩。

常用的信號(hào):

信號(hào)信號(hào) 信號(hào)名稱(chēng) 縮寫(xiě) 描述
1 SIGHUP HUP 中止:注銷(xiāo)或者終端失去連接時(shí)發(fā)送給進(jìn)程
2 SIGINT INT 中斷:當(dāng)按下^C鍵時(shí)發(fā)送
9 SIGKILL KILL 殺死:立即終止
15 SIGTERM TERM 終止:請(qǐng)求終止
18 SIGCONT CONT 繼續(xù):恢復(fù)掛起的進(jìn)程锅劝,由fgbg發(fā)送
19 SIGSTOP STOP 停止(掛起):當(dāng)按下^Z鍵時(shí)發(fā)送

信號(hào)用于簡(jiǎn)單的娜谊,但是重要的進(jìn)程間控制形式派草。當(dāng)使用kill向進(jìn)程發(fā)送信號(hào)時(shí)搀缠,可以使用信號(hào)的編號(hào)、名稱(chēng)或者縮寫(xiě)指定近迁。如果使用名稱(chēng)或縮寫(xiě)艺普,則一定要使用大寫(xiě)字母。

例:使用kill -l命令查看所有信號(hào)

[07:43 @nosee ~/Desktop]$ 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    

注:出于安全考慮鉴竭,常規(guī)的用戶(hù)標(biāo)識(shí)只能向自己的進(jìn)程發(fā)送信號(hào)歧譬。但是,超級(jí)用戶(hù)允許向系統(tǒng)上的任何進(jìn)程發(fā)送信號(hào)搏存。

八瑰步、參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缩焦,一起剝皮案震驚了整個(gè)濱河市兵钮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌舌界,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泰演,死亡現(xiàn)場(chǎng)離奇詭異呻拌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)睦焕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)藐握,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人垃喊,你說(shuō)我怎么就攤上這事猾普。” “怎么了本谜?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵初家,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我乌助,道長(zhǎng)溜在,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任他托,我火速辦了婚禮掖肋,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赏参。我一直安慰自己志笼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布把篓。 她就那樣靜靜地躺著纫溃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪韧掩。 梳的紋絲不亂的頭發(fā)上皇耗,一...
    開(kāi)封第一講書(shū)人閱讀 51,737評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音揍很,去河邊找鬼郎楼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛窒悔,可吹牛的內(nèi)容都是我干的呜袁。 我是一名探鬼主播,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼简珠,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼阶界!你這毒婦竟也來(lái)了虹钮?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤膘融,失蹤者是張志新(化名)和其女友劉穎芙粱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體氧映,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡春畔,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了岛都。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片律姨。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖臼疫,靈堂內(nèi)的尸體忽然破棺而出择份,到底是詐尸還是另有隱情,我是刑警寧澤烫堤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布荣赶,位于F島的核電站,受9級(jí)特大地震影響鸽斟,放射性物質(zhì)發(fā)生泄漏讯壶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一湾盗、第九天 我趴在偏房一處隱蔽的房頂上張望伏蚊。 院中可真熱鬧,春花似錦格粪、人聲如沸躏吊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)比伏。三九已至,卻和暖如春疆导,著一層夾襖步出監(jiān)牢的瞬間赁项,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工澈段, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悠菜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓败富,卻偏偏與公主長(zhǎng)得像悔醋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兽叮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容