1、使用命令行啓動、撤銷進程python
1)啓動進程linux
linux啓動進程的命令能夠用sh,python ,./文件名安全
這裏我編寫的是Python文件做爲演示,因此用Python 文件名建立進程多線程
上面,我用vi編輯了一個名爲test的py文件,用cat命令查看文件內容,該程序主要是執行3秒鐘輸出一條「我是一個進程」的字符串,及當前時間戳,一共輸出三次。而後,用python 文件名的命令執行該程序,運行結果如上併發
2)查看進程函數
咱們能夠用conky查看進程中是否有py文件在執行性能
運行程序能夠看到,有一個進程號爲6622的Python文件正在執行ui
如今我將程序改了一下,讓他陷入一個死循環,而且每隔3秒輸出指定內容以及他的進程號。spa
從運行結果能夠看出,進程號是6773。linux在啓動一個進程時,系統會在/proc下建立一個以pid命名的文件夾,該文件夾下存放了進程的信息,其中包括一個名爲exe的文件即記錄了絕對路徑,經過ll或ls –l命令便可查看。因而咱們進入到/proc/6773文件夾下操作系統
cwd符號連接的是進程運行目錄,exe符號鏈接就是執行程序的絕對路徑
一樣能夠查看進程的命令還有top和ps:
top是一個即時顯示process動態的命令:
使用方式:top [-] [d delay] [q] [c] [S] [s] [i] [n] [b]
d :改變顯示的更新速度,或是在交談式指令列( interactive command)按s
q :沒有任何延遲的顯示速度,若是使用者是有superuser的權限,則top將會以最高的優先序執行
c :切換顯示模式,共有兩種模式,一是隻顯示執行檔的名稱,另外一種是顯示完整的路徑與名稱
S :累積模式,會將己完成或消失的子行程( dead child process )的CPU time累積起來
s :安全模式,將交談式指令取消,避免潛在的危機
i :不顯示任何閒置(idle)或無用(zombie)的行程
n :更新的次數,完成後將會退出top
b :批次檔模式,搭配"n"參數一塊兒使用,能夠用來將top的結果輸出到檔案內
Ps能夠顯示瞬間行程 (process) 的動態:
使用方式:ps [options] [--help]
參數:ps的參數很是多, 在此僅列出幾個經常使用的參數並大略介紹含義
-A 列出全部的進程
-w 顯示加寬能夠顯示較多的資訊
-au 顯示較詳細的資訊
-aux 顯示全部包含其餘使用者的行程
3)結束進程
進程的退出有兩種狀況,一種是當程序執行完成後正常退出,還有一種就是由用戶強行終止,如今,咱們的程序是死循環,是沒法正常退出的,因而,咱們須要用kill命令強行終止他,kill -9 pid
2、調用系統函數接口
1)建立進程(多個)
fork()函數能夠建立進程,他的實質是一個進程的克隆,建立的進程獨立於父進程單獨存在,父子兩個進程同時運行,若是fork()函數返回的是0,則表明該進程是子進程,若返回的值大於0,則表明父進程,若小於0,則表明進程建立失敗,且父子進程pid不一樣
把以前的py文件改一下,在建立子進程前輸出一次當前進程的pid,即父進程pid,而後建立子進程,根據fork()返回的子進程pid值輸出對應進程的pid,重複執行兩次,且每次間隔3秒
從上面的運行結果能夠看出,在建立子進程前的進程pid是父進程的pid:7188,建立後不只存在父進程的pid,還多出了子進程的pid:7189,且兩個進程相互獨立,都在循環中重複了兩次,最明顯從程序末尾「結束進程」輸出了兩次能夠看出
這裏我只是用fork()建立了一個子進程,下面我將用他來建立多個子進程
上面這段程序的意思是,用一個for循環屢次(這裏是三次)建立子進程,且每次均由父進程建立,若fork()的返回值小於等於0,則退出for循環,執行下面的內容,而父進程則要建立滿三次後才能繼續執行下面的內容,這裏要有一種並行的思惟,不能以單一的流水線看待程序的執行,很明顯的,從程序末尾輸出「進程結束」四次也能夠看出建立成功(三個子進程,一個父進程),從fork()的賦值也能夠看出,fork()建立出的子進程不會覆蓋以前存在的進程,這也體現了一種並行的思惟
2)進程的併發執行
進程數量少於空閒cpu數目:
首先來看看怎樣查看cpu的數量,方法不少,舉幾個特別的例子。
一、在/proc/cpuinfo中存放了cpu的基本信息,咱們能夠用過他來查看
能夠看到,這裏列出的processor從0到1,他是邏輯處理器的id,故共有兩個邏輯cpu
二、將/proc/cpuinfo經過管道過濾處理一下
能夠看到有兩個邏輯cpu
三、經過Python的multiprocessing庫中的cpu_count()函數獲取
下面,我來改一下test.py文件,讓他執行的大意爲建立一個子進程,父子進程並行執行一個二次累乘運算,每次運算後延時2秒,而後輸出各自的pid及進程執行時間
上面是兩個進程並行的狀況,下面我再來改一下,改爲只有一個進程跑
進程數量大於空閒cpu數目:
這裏我建立三個子進程,也就是四個進程並行,來看下他的執行時間
再來看看cpu的使用狀況:
上面這是兩個進程的cpu佔用率
上面這是多個cpu的佔用率,能夠看出,進程數大於cpu邏輯數時,單個程序對cpu的佔用率降低了,但執行速度仍是進程數小於cpu邏輯數的狀況下要快些,這是由於,進程數與CPU核數一致的狀況下,能夠減小沒必要要的由於系統調度形成的性能損失,在進程與CPU調度的關係中,單個核心處理多個進程的時候,是排隊處理的,因此將進程數量設置超過核心數是沒有太大意義的。
父進程阻塞等待子進程:
下面再用/proc來看看,當用wait()阻塞父進程時,父子進程的狀態是怎樣的:
這是改了以後的代碼,爲方便查看狀態讓父子兩個進程循環輸出進程號,這裏flag的做用是,讓wait()函數在while循環中只執行一次,當子進程結束後便可喚醒父進程:
那麼一開始執行的時候,只有子進程在運行,父進程備阻塞了,經過命令:/proc/[pid]/status能夠看到此時父進程的狀態是sleeping的:
而子進程的狀態是running:
接着,咱們kill掉子進程,喚醒父進程,父進程此時的狀態就變成Running了:
父子進程執行不一樣的可執行文件:
我把函數改爲這樣,讓子進程在執行時經過execl()函數調用child_test.py文件,輸出各自的進程號,能夠看到,雖然子進程調用了child_test.py但他們的進程號都是同樣的
生成3層或以上的父子進程樹:
這裏我生成三層進程樹,爲方便查看其關係,每層均爲一個進程,flag用來確保第三層只有一個進程,py文件以下:
下面,咱們用/proc命令查看,首先來系統的介紹一下/proc文件:
/proc文件系統,不是普通的文件系統,而是系統內核的映像,該目錄中的文件時存放在系統內存中的,它以文件系統的形式爲訪問系統內核數據的操做提供接口。
/proc文件下有根據進程號排列的信息:
以前用到的查看進程詳細信息,就是到/proc/pid/status下查看的
/proc/pid/cmdline 進程啓動命令
/proc/pid/cwd 連接到進程當前工做目錄
/proc/pid/environ 進程環境變量列表
/proc/pid/exe 連接到進程的執行命令文件
/proc/pid/fd 包含進程相關的全部的文件描述符
/proc/pid/maps 與進程相關的內存映射信息
/proc/pid/mem 指代進程持有的內存,不可讀
/proc/pid/root 連接到進程的根目錄
/proc/pid/stat 進程的狀態
/proc/pid/statm 進程使用的內存的狀態
/proc/pid/status 進程狀態信息,比stat/statm更具可讀性
/proc/self 連接到當前正在運行的進程
下面咱們就用/proc/pid/status來查看父子進程樹的關係:
這是查看第三層子進程的status文件結果
這裏的Pid是當前進程的id,這裏的PPid是當前進程的父進程id,Threads表示當前進程的線程數,從上面能夠看出該進程的pid是19744,他的父進程的pid爲19743,而後咱們又用proc查看pid爲19743的status文件:
能夠看到,pid爲19743的進程,他的父進程pid爲19742,這和咱們運行程序跑出來的結果相同
Linux狀態間的轉換:
Linux的狀態有:
Linux進程狀態:R (TASK_RUNNING),可執行狀態。
Linux進程狀態:S (TASK_INTERRUPTIBLE),可中斷的睡眠狀態。
Linux進程狀態:D (TASK_UNINTERRUPTIBLE),不可中斷的睡眠狀態。
Linux進程狀態:Z (TASK_DEAD - EXIT_ZOMBIE),退出狀態,進程成爲殭屍進程。
Linux進程狀態:T (TASK_STOPPED or TASK_TRACED),暫停狀態或跟蹤狀態。
Linux進程狀態:X (TASK_DEAD - EXIT_DEAD),退出狀態,進程即將被銷燬。
只有當進程從「內核運行態」轉移到「睡眠狀態」時,內核纔會進行進程切換操做。在內核態下運行的進程不能被其它進程搶佔,並且一個進程不能改變另外一個進程的狀態。爲了不進程切換時形成內核數據錯誤,內核在執行臨界區代碼時會禁止一切中斷。
PID和tgid字段:
PID是一個數字,用於標識一個進程,就像學生的學號同樣,每一個進程都有一個惟一的編號,保存在進程描述符的pid字段中。通常的,在系統運行期間,PID都是被順序編號,好比進程A的PID爲10,那下個建立的進程的PID則爲11。不過PID的值有一個上限,當內核使用的PID達到這個上限後就會循環開始找已閒置的小PID號。在缺省狀態下,最大PID值爲32767(PID_MAX_DEFAULT - 1);能夠經過修改/proc/sys/kernel/pid_max這個文件來減少PID上限值。而在64位系統中,PID可擴大到4194303。
內核是經過一個叫pidmap的位圖來管理已分配的PID號和閒置的PID號。在32位系統中,pidmap的大小就是一個頁框的大小(4KB),而一個頁框大小爲32768位,也就是每一位表明一個PID號,1表明此PID已經被分配,0表明此PID號未被使用;而在64位系統下,pidmap會使用多個頁框。
在POSIX標準中規定了一個多線程應用程序中全部的線程都必須有相同的PID,在linux內核中,是使用輕量級進程實現線程的功能,可是輕量級進程也是一個進程,他們的PID都不相同,爲了實現這一點,內核在進程描述符中引入了tgid字段。在linux的線程組概念中,一個線程組中全部線程使用的該線程組領頭線程相同的PID,也就是該組第一個輕量級進程的PID,並保存到進程描述符的tgid字段中
進程間關係:
在系統中,除了進程0,一個進程是由另外一個進程建立,它們都具備父子關係。若是一個進程建立多個子進程,則子進程之間有兄弟關係。在整個系統啓動期間,會初始化系統的第一個進程init_task,這個進程屬於內核中的一個進程,它算是全部進程的祖先,以後它會啓動PID爲1的init進程和PID爲2的kthreadd,這兩個進程以後啓動的全部進程,而init_task以後會轉變爲一個idle進程用於CPU空閒時運行。在進程描述符中,使用real_parent、parent、children、sibling這幾個指針將進程關係組織在一塊兒
以上操做系統做業...不正確的地方請高手糾正