Python Day34
UDP協議:
?用戶數據報協議,是OSI模型中屬于傳輸層的協議。提供不可靠的,不要求順序的,數據量小的,速度快的傳輸服務。
不可靠:發送完成后不需要確認信息,并且立即刪除緩存中的數據。
不要求順序:當一個數據較大時,會分為多個數據報來傳輸,對方無法獲知數據的順序,
以及是否完整。
數據量較小的:數據越大,越容易丟包,所以盡量發送數據量小的建議不要超過1472、
速度快:相對于TCP來說不需要確認信息,不需要建立,甚至不管收不到,只管發,所以傳輸效率高。
通訊流程:
如果TCP比喻為手機打電話的過程,那么UDP可以看做是對講機
1.買機器? 創建UDP的socket
2.固定頻道? ? bind一個ip和端口
3.收發數據? ? ? recvfrom? ?sendto
?
接收:
1.買機器? ?創建UDP的socket
2.收發數據? recvfrom sendto
注意:不能先收,要收數據,必須明確端口號,沒有端口號是不可能使用網絡服務的。
?
TCP與UDP的其他區別:
1.不會粘包,每次發送都是一個獨立的數據報
2.不需要建立連接
TCP:對數據完整性要求較高:在線支付,文字信息
UDP:對數據不要完整性,但是要快:視頻,語音,游戲
DNS:
域名解析服務器
域名就是一串有規律的字符串,用來綁定IP,目的是為了方便記憶。
域名解析服務器 就是幫你把域名轉換為ip地址,本質上就是一個大型的數據庫系統,里面有域名和IP的對應關系
一臺機器性能有限:
分為:
根域名服務器? 只存儲頂級域名服務器的信息
頂級域名服務器? 只存儲二級域名服務器
二級域名服務器? 只存儲三級域名服務器
三級域名? 通常直接存儲具體的ip信息
?
本地DNS? 用于加速解析
?
自己搭建DNS的作用:
1.CDN 內容分發網絡? ?就是在你的周圍建立更多鏡像服務
2.集群
操作系統:
也是一個軟件,受代碼保護的不能隨意修改,代碼量巨大,內核就有500萬以上
長壽,一旦完成一般不改。
1.第一帶計算機 真空管和穿孔卡片 沒有進程 沒有操作系統
2.第二代計算機 7094 1401 晶體管 批處理系統
輸入輸出 以及計算設備 不能互聯 需要人參與 一批一批的處理 開發效率慢 并且串行執行
3.第三代計算機 集成電路 與多道技術
多終端聯機 spooling 同一臺機器既能進行科學計算 又能做字符處理 通用計算機
多道技術 解決串行導致的效率低下問題
多用戶終端 可以同時為多個用戶提供服務 每個用戶以為自己獨享一臺計算機
4.第四代 個人電腦
大規模使用了集成電路,大多都提供了GUI界面
多道技術:
產生背景:所有程序串行,導致資源浪費。目的是讓多個程序可以并發執行,同時處理多個任務。
關鍵技術:
空間復用:指的是 同一時間內存中加載多個不同程序數據。每個進程間內存區域相互隔離,物理層面的隔離。
時間復用:切換加保存
切換條件:1.一個進程執行過程中遇到了IO操作,切換到其他進程
2.運行時間過長,會被操作系統強行剝奪執行權力
單純的切換不夠,必須在切換前保存當前的狀態,以便于回復執行。
進程:
一個正在被運行的程序就稱之為進程,是程序具體執行過程,一種抽象概念,進程來自于操作系統
多進程:
進程與程序的區別:
程序就是一堆計算機可以識別文件,程序在沒有運行時就是一堆躺在硬盤上的二進制數據,
運行的時將數據從硬盤讀入內存,然后cpu再將數據從內存讀出并執行指令。
一旦程序運行就有了進程,一個程序可以多次運行但進程與進程之間是獨立的。
當我們右鍵運行了一個py文件時,其實啟動的是python解釋器,你的py文件其實是當作參數傳給了解釋器。
阻塞,非阻塞,并行,并發:
阻塞:就是程序遇到io操作,非阻塞就是程序沒有遇到io操作。并發:多個任務同時發生,但不是同時執行本質上是切換執行,只是速度很快。
并行:多個任務真正的同時執行,必須具備多核CPU,才可能并行。
并發,并行說的是任務的處理方式。
程序員永恒的話題:
提高效率,根本方法就是讓程序盡可能處于運行狀態。
減少IO 盡可能多占用CPU時間,緩沖區就是用于減少IO操作的。
PID和PPID:
PID:
在一個操作系統中通常都會運行多個應用程序,也就是多個進程,那么如何來區別進程呢?
系統會給每一個進程分配一個進程編號即PID,如同人需要一個身份證號來區分。
驗證:
tasklist用于查看所有的進程信息。
taskkill/f/pid/ pid? ?該命令可以用于結束指定進程。
在python中可以使用os模塊來獲取pid
import? os
print(os.getpid())
PPID:
當一個進程a開啟了另一個進程b時,a稱為b的父進程,b稱為a的子進程,在python中可以通過os模塊來獲取父進程的pid。
import os
print("self", os.getppid())?
如果是在pycharm中運行的py文件,那pycharm就是這個python.exe的父進程,當然你可以從cmd
中來運行py文件,那此時cmd就是python.exe的父進程。
并發與并行,阻塞與非阻塞:
并發指的是多個事件同時發生了:
例如洗衣服和做飯,同時發生了,但本質上是兩個任務在切換,給人的感覺是同時在進行著,也被稱為偽并行。
并行指的是,多個事情同時進行著:
例如一個人在寫代碼而另一個人在寫書,這2個事情是同時進行的,要注意的是一個人是無法真正的并行執行任務的,在計算機中單核CPU也是無法真正并行的,之所以單核CPU也能同時運行qq和微信,其實就是并發。
阻塞與非阻塞指的是程序的狀態
進程有三種狀態:
就緒態,運行態和阻塞態
多道技術會在進程執行時間過長或遇到IO時自動切換其他進程,意味著IO操作與進程被剝奪CPU執行權都會造成進程無法繼續執行。
進程相關理論:
但凡是硬件,都需要有操作系統去管理,只要有操作系統,就有進程的概念,就需要有創建進程的方式 ,一些操作系統只為一個應用程序設計,比如微波爐中的控制器,一旦啟動微波爐,進程就存在。
而對于通用系統(跑很多應用程序),需要有系統運行過程中創建或撤銷進程的能力,主要分為4種形式創建新的進程
一個進程在運行過程中開啟了子進程(如nginx開啟多進程,os.fork,subprocess.Popen等)
用戶的交互式請求,而創建一個新進程(如用戶雙擊暴風影音)
一個批處理作業的初始化(只在大型機的批處理系統中應用)
無論哪一種,新進程的創建都是由一個已經存在的進程執行了一個用于創建進程的系統調用而創建,
在windows中該系統調用是:CreateProcess,CreateProcess既處理進程的創建,也負責把正確的程序裝入新進程。
1.相同的是:進程創建后,父進程和子進程有各自不同的地址空間(多道技術要求物理層面實現進程之間內存的隔離),任何一個進程的在其地址空間中的修改都不會影響到另外一個進程。
2.不同的是:在UNIX中,子進程的初始地址空間是父進程的一個副本,提示:子進程和父進程是可以有只讀的共享內存區的。但是對于windows系統來說,會重新加載程序代碼。
進程的銷毀:
出錯退出(自愿,python a.py中a.py不存在)
嚴重錯誤(非自愿,執行非法指令,如引用不存在的內存,1/0等,可以捕捉異常,try...except...)
被其他進程殺死(非自愿,如kill -9)
無論UNIX還是windows,進程只有一個父進程,不同的是:
在UNIX中所有的進程,都是以init進程為根,組成樹形結構。父子進程共同組成一個進程組,這樣,當從鍵盤發出一個信號時,該信號被送給當前與鍵盤相關的進程組中的所有成員。
在windows中,沒有進程層次的概念,所有的進程都是地位相同的,唯一類似于進程層次的暗示,是在創建進程時,父進程得到一個特別的令牌(稱為句柄),該句柄可以用來控制子進程,但是父進程有權把該句柄傳給其他子進程,這樣就沒有層次了。
python中實現多進程
在一個應用程序中可能會有多個任務需要并發執行,但是對于操作系統而言,一個進程就是一個任務,CPU會從上往下依次執行代碼,當代碼中遇到IO操作時,操作系統就會剝奪CPU執行權給其他應用程序,這樣對于當前應用程序而言,效率就降低了,如何使得程序既能完成任務又不降低效率呢?答案就是讓把當前程序中的耗時操作交給子進程來完成,如此當前應用程序可以繼續執行其他任務
方式1:
實例化Process類
from multiprocessing import Process
import time
def task(name):
print('%s is running' %name)
time.sleep(3)
print('%s is done' %name)
if __name__ == '__main__':
# 在windows系統之上,開啟子進程的操作一定要放到這下面
# Process(target=task,kwargs={'name':'egon'})
p=Process(target=task,args=('jack',))
p.start() # 向操作系統發送請求,操作系統會申請內存空間,然后把父進程的數據拷貝給子進程,作為子進程的初始狀態
print('======主')
?
方式2:
繼承Process類 并覆蓋run方法
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self,name):
super(MyProcess,self).__init__()
self.name=name
def run(self):
print('%s is running' %self.name)
time.sleep(3)
print('%s is done' %self.name)
if __name__ == '__main__':
p=MyProcess('jack')
p.start()
print('主')
join函數
調用start函數后的操作就由操作系統來玩了,至于何時開啟進程,進程何時執行,何時結束都與應用程序無關,所以當前進程會繼續往下執行,join函數就可以是父進程等待子進程結束后繼續執行
?
from multiprocessing import Process
def task(n):
print('%s is runing' %n)
time.sleep(n)
if __name__ == '__main__':
start_time=time.time()
p1=Process(target=task,args=(1,),name='任務1')
p1.start() # 啟動進程
print(p1.pid) # 獲取進程pid
print(p1.name) # 獲取進程名字
p1.terminate() # 終止進程
p1.join() # 提高優先級
print(p1.is_alive()) # 獲取進程的存活狀態
print('主')
什么是孤兒進程
孤兒進程指的是開啟子進程后,父進程先于子進程終止了,那這個子進程就稱之為孤兒進程
例如:qq聊天中別人發給你一個鏈接,點擊后打開了瀏覽器,那qq就是瀏覽器的父進程,然后退出qq,此時瀏覽器就成了孤兒進程
孤兒進程是無害的,有其存在的必要性,在父進程結束后,其子進程會被操作系統接管。
?
什么是僵尸進程
僵尸進程指的是,當子進程比父進程先結束,而父進程又沒有回收子進程,釋放子進程占用的資源,此時子進程將成為一個僵尸進程。如果父進程先退出 ,子進程被操作系統接管,子進程退出后操作系統會回收其占用的相關資源!
僵尸進程的危害:
由于子進程的結束和父進程的運行是一個異步過程,即父進程永遠無法預測子進程 到底什么時候結束. 那么會不會因為父進程太忙來不及wait子進程,或者說不知道 子進程什么時候結束,而丟失子進程結束時的狀態信息呢? 不會。因為UNⅨ提供了一種機制可以保證只要父進程想知道子進程結束時的狀態信息, 就必然可以得到。這種機制就是: 在每個進程退出的時候,內核釋放該進程所有的資源,包括打開的文件,占用的內存等。但是仍然為其保留一定的信息(包括進程號the process ID,退出狀態the termination status of the process,運行時間the amount of CPU time taken by the process等)。直到父進程通過wait / waitpid來取時才釋放. 但這樣就導致了問題,如果進程不調用wait / waitpid的話,那么保留的那段信息就不會釋放,其進程號就會一直被占用,但是系統所能使用的進程號是有限的,如果大量的產生[僵死進程],將因為沒有可用的進程號而導致系統不能產生新的進程. 此為僵尸進程的危害,應當避免。
?
轉載于:https://www.cnblogs.com/xinfan1/p/10957087.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Python Day34的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 码code | 巧用2种方法,打破20条
- 下一篇: Linux学习记录-11