1. 程式人生 > >python3全棧開發-補充UDP的套接字、操作系統、並發的理論基礎

python3全棧開發-補充UDP的套接字、操作系統、並發的理論基礎

共享 solaris 小時 如何實現 bfc 讀取數據 ram strong 網絡接口

一、基於UDP的套接字

udp套接字簡單示例

技術分享圖片
import socket
ip_port=(1.1.1.1,8181)
BUFSIZE=1024
udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

udp_server_client.bind(ip_port)

while True:
    msg,addr=udp_server_client.recvfrom(BUFSIZE)
    print(msg,addr)

    udp_server_client.sendto(msg.upper(),addr)
udp服務端 技術分享圖片
import socket
ip_port=(1.1.1.1,9000)
BUFSIZE=1024
udp_server_client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

while True:
    msg=input(>>: ).strip()
    if not msg:continue

    udp_server_client.sendto(msg.encode(utf-8),ip_port)

    back_msg,addr=udp_server_client.recvfrom(BUFSIZE)
    
print(back_msg.decode(utf-8),addr)
udp客戶端

時間服務器

技術分享圖片
from socket import *
from time import strftime

ip_port=(127.0.0.1,9000)
bufsize=1024

tcp_server=socket(AF_INET,SOCK_DGRAM)
tcp_server.bind(ip_port)

while True:
    msg,addr=tcp_server.recvfrom(bufsize)
    print(===>,msg)
    
    
if not msg: time_fmt=%Y-%m-%d %X else: time_fmt=msg.decode(utf-8) back_msg=strftime(time_fmt) tcp_server.sendto(back_msg.encode(utf-8),addr) tcp_server.close()
ntp服務端 技術分享圖片
from socket import *
ip_port=(127.0.0.1,9000)
bufsize=1024

tcp_client=socket(AF_INET,SOCK_DGRAM)

while True:
    msg=input(請輸入時間格式(例%Y %m %d)>>: ).strip()
    tcp_client.sendto(msg.encode(utf-8),ip_port)

    data=tcp_client.recv(bufsize)

    print(data.decode(utf-8))

tcp_client.close()
ntp客戶端

讓我們再基於udp制作一個遠程執行命令的程序

技術分享圖片
from socket import *
import subprocess

ip_port=(127.0.0.1,9003)
bufsize=1024

udp_server=socket(AF_INET,SOCK_DGRAM)
udp_server.bind(ip_port)

while True:
    #收消息
    cmd,addr=udp_server.recvfrom(bufsize)
    print(用戶命令----->,cmd)

    #邏輯處理
    res=subprocess.Popen(cmd.decode(utf-8),shell=True,stderr=subprocess.PIPE,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
    stderr=res.stderr.read()
    stdout=res.stdout.read()

    #發消息
    udp_server.sendto(stderr,addr)
    udp_server.sendto(stdout,addr)
udp_server.close()
udp不粘包服務端 技術分享圖片
from socket import *
ip_port=(127.0.0.1,9003)
bufsize=1024

udp_client=socket(AF_INET,SOCK_DGRAM)

while True:
    msg=input(>>: ).strip()
    udp_client.sendto(msg.encode(utf-8),ip_port)

    data,addr=udp_client.recvfrom(bufsize)
    print(data.decode(utf-8),end=‘‘)
udp不粘包客戶端

上述程序是基於udp的socket,在運行時永遠不會發生粘包

二、什麽是進程

顧名思義,進程即正在執行的一個過程。進程是對正在運行程序的一個抽象。

進程的概念起源於操作系統,是操作系統最核心的概念,也是操作系統提供的最古老也是最重要的抽象概念之一。操作系統的其他所有內容都是圍繞進程的概念展開的。

所以想要真正了解進程,必須事先了解操作系統

三、操作系統

1、 為什麽要有操作系統

現代的計算機系統主要是由一個或者多個處理器,主存,硬盤,鍵盤,鼠標,顯示器,打印機,網絡接口及其他輸入輸出設備組成。

一般而言,現代計算機系統是一個復雜的系統。

其一:如果每位應用程序員都必須掌握該系統所有的細節,那就不可能再編寫代碼了(嚴重影響了程序員的開發效率:全部掌握這些細節可能需要一萬年....)

其二:並且管理這些部件並加以優化使用,是一件極富挑戰性的工作,於是,計算安裝了一層軟件(系統軟件),稱為操作系統。它的任務就是為用戶程序提供一個更好、更簡單、更清晰的計算機模型,並管理剛才提到的所有設備。

總結:

程序員無法把所有的硬件操作細節都了解到,管理這些硬件並且加以優化使用是非常繁瑣的工作,這個繁瑣的工作就是操作系統來幹的,有了他,程序員就從這些繁瑣的工作中解脫了出來,只需要考慮自己的應用軟件的編寫就可以了,應用軟件直接使用操作系統提供的功能來間接使用硬件。

2、 什麽是操作系統

精簡的說的話,操作系統就是一個協調、管理和控制計算機硬件資源和軟件資源的控制程序。操作系統所處的位置如圖1

#操作系統位於計算機硬件與應用軟件之間,本質也是一個軟件。

操作系統由操作系統的內核(運行於內核態,管理硬件資源)以及系統調用(運行於用戶態,為應用程序員寫的應用程序提供系統調用接口)兩部分組成,

所以,單純的說操作系統是運行於內核態的,是不準確的。

技術分享圖片

圖1

細說的話,操作系統應該分成兩部分功能:

#一:隱藏了醜陋的硬件調用接口,為應用程序員提供調用硬件資源的更好,更簡單,更清晰的模型(系統調用接口)。
應用程序員有了這些接口後,就不用再考慮操作硬件的細節,專心開發自己的應用程序即可。 例如:操作系統提供了文件這個抽象概念,對文件的操作就是對磁盤的操作,有了文件我們無需再去考慮關於磁盤的讀寫控制(比如控制磁盤轉動,移動磁頭讀寫數據等細節), #二:將應用程序對硬件資源的競態請求變得有序化 例如:很多應用軟件其實是共享一套計算機硬件,比方說有可能有三個應用程序同時需要申請打印機來輸出內容,
那麽a程序競爭到了打印機資源就打印,然後可能是b競爭到打印機資源,也可能是c,這就導致了無序,打印機可能打印一段a的內容然後又去打印c...,操作系統的一個功能就是將這種無序變得有序。
技術分享圖片
#作用一:為應用程序提供如何使用硬件資源的抽象
例如:操作系統提供了文件這個抽象概念,對文件的操作就是對磁盤的操作,有了文件我們無需再去考慮關於磁盤的讀寫控制

註意:
操作系統提供給應用程序的該抽象是簡單,清晰,優雅的。為何要提供該抽象呢?
硬件廠商需要為操作系統提供自己硬件的驅動程序(設備驅動,這也是為何我們要使用聲卡,就必須安裝聲卡驅動。。。),廠商為了節省成本或者兼容舊的硬件,它們的驅動程序是復雜且醜陋的
操作系統就是為了隱藏這些醜陋的信息,從而為用戶提供更好的接口
這樣用戶使用的shell,Gnome,KDE看到的是不同的界面,但其實都使用了同一套由linux系統提供的抽象接口


#作用二:管理硬件資源
現代的操作系統運行同時運行多道程序,操作系統的任務是在相互競爭的程序之間有序地控制對處理器、存儲器以及其他I/O接口設備的分配。
例如:
同一臺計算機上同時運行三個程序,它們三個想在同一時刻在同一臺計算機上輸出結果,那麽開始的幾行可能是程序1的輸出,接著幾行是程序2的輸出,然後又是程序3的輸出,最終將是一團糟(程序之間是一種互相競爭資源的過程)
操作系統將打印機的結果送到磁盤的緩沖區,在一個程序完全結束後,才將暫存在磁盤上的文件送到打印機輸出,同時其他的程序可以繼續產生更多的輸出結果(這些程序的輸出沒有真正的送到打印機),這樣,操作系統就將由競爭產生的無序變得有序化。
詳解

技術分享圖片

圖 2

3、操作系統與普通軟件的區別

1.主要區別是:你不想用暴風影音了你可以選擇用迅雷播放器或者幹脆自己寫一個,但是你無法寫一個屬於操作系統一部分的程序(時鐘中斷處理程序),操作系統由硬件保護,不能被用戶修改。

2.操作系統與用戶程序的差異並不在於二者所處的地位。特別地,操作系統是一個大型、復雜、長壽的軟件,

  • 大型:linux或windows的源代碼有五百萬行數量級。按照每頁50行共1000行的書來算,五百萬行要有100卷,要用一整個書架子來擺置,這還僅僅是內核部分。用戶程序,如GUI,庫以及基本應用軟件(如windows Explorer等),很容易就能達到這個數量的10倍或者20倍之多。
  • 長壽:操作系統很難編寫,如此大的代碼量,一旦完成,操作系統所有者便不會輕易扔掉,再寫一個。而是在原有的基礎上進行改進。(基本上可以把windows95/98/Me看出一個操作系統,而windows NT/2000/XP/Vista則是兩位一個操作系統,對於用戶來說它們十分相似。還有UNIX以及它的變體和克隆版本也演化了多年,如System V版,Solaris以及FreeBSD等都是Unix的原始版,不過盡管linux非常依照UNIX模式而仿制,並且與UNIX高度兼容,但是linux具有全新的代碼基礎)

4、操作系統發展史

第一代計算機(1940~1955):真空管和穿孔卡片

第一代計算機的產生背景:

第一代之前人類是想用機械取代人力,第一代計算機的產生是計算機由機械時代進入電子時代的標誌,從Babbage失敗之後一直到第二次世界大戰,數字計算機的建造幾乎沒有什麽進展,第二次世界大戰刺激了有關計算機研究的爆炸性進展。

lowa州立大學的john Atanasoff教授和他的學生Clifford Berry建造了據認為是第一臺可工作的數字計算機。該機器使用300個真空管。大約在同時,Konrad Zuse在柏林用繼電器構建了Z3計算機,英格蘭布萊切利園的一個小組在1944年構建了Colossus,Howard Aiken在哈佛大學建造了Mark 1,賓夕法尼亞大學的William Mauchley和他的學生J.Presper Eckert建造了ENIAC。這些機器有的是二進制的,有的使用真空管,有的是可編程的,但都非常原始,設置需要花費數秒鐘時間才能完成最簡單的運算。

在這個時期,同一個小組裏的工程師們,設計、建造、編程、操作及維護同一臺機器,所有的程序設計是用純粹的機器語言編寫的,甚至更糟糕,需要通過成千上萬根電纜接到插件板上連成電路來控制機器的基本功能。沒有程序設計語言(匯編也沒有),操作系統則是從來都沒聽說過。使用機器的過程更加原始,詳見下‘工作過程’

特點:
沒有操作系統的概念
所有的程序設計都是直接操控硬件

工作過程:
程序員在墻上的機時表預約一段時間,然後程序員拿著他的插件版到機房裏,將自己的插件板街道計算機裏,這幾個小時內他獨享整個計算機資源,後面的一批人都得等著(兩萬多個真空管經常會有被燒壞的情況出現)。

後來出現了穿孔卡片,可以將程序寫在卡片上,然後讀入機而不用插件板

優點:

程序員在申請的時間段內獨享整個資源,可以即時地調試自己的程序(有bug可以立刻處理)

缺點:

浪費計算機資源,一個時間段內只有一個人用。
註意:同一時刻只有一個程序在內存中,被cpu調用執行,比方說10個程序的執行,是串行的

第二代計算機(1955~1965):晶體管和批處理系統

第二代計算機的產生背景:

由於當時的計算機非常昂貴,自認很自然的想辦法較少機時的浪費。通常采用的方法就是批處理系統。

特點:
設計人員、生產人員、操作人員、程序人員和維護人員直接有了明確的分工,計算機被鎖在專用空調房間中,由專業操作人員運行,這便是‘大型機’。

有了操作系統的概念

有了程序設計語言:FORTRAN語言或匯編語言,寫到紙上,然後穿孔打成卡片,再講卡片盒帶到輸入室,交給操作員,然後喝著咖啡等待輸出接口

工作過程:插圖

技術分享圖片

技術分享圖片

第二代如何解決第一代的問題/缺點:
1.把一堆人的輸入攢成一大波輸入,
2.然後順序計算(這是有問題的,但是第二代計算也沒有解決)
3.把一堆人的輸出攢成一大波輸出

現代操作系統的前身:(見圖)

優點:批處理,節省了機時

缺點:
1.整個流程需要人參與控制,將磁帶搬來搬去(中間倆小人)

2.計算的過程仍然是順序計算-》串行

3.程序員原來獨享一段時間的計算機,現在必須被統一規劃到一批作業中,等待結果和重新調試的過程都需要等同批次的其他程序都運作完才可以(這極大的影響了程序的開發效率,無法及時調試程序)

第三代計算機(1965~1980):集成電路芯片和多道程序設計

第三代計算機的產生背景:

20世紀60年代初期,大多數計算機廠商都有兩條完全不兼容的生產線。

一條是面向字的:大型的科學計算機,如IBM 7094,見上圖,主要用於科學計算和工程計算

另外一條是面向字符的:商用計算機,如IBM 1401,見上圖,主要用於銀行和保險公司從事磁帶歸檔和打印服務

開發和維護完全不同的產品是昂貴的,同時不同的用戶對計算機的用途不同。

IBM公司試圖通過引入system/360系列來同時滿足科學計算和商業計算,360系列低檔機與1401相當,高檔機比7094功能強很多,不同的性能賣不同的價格

360是第一個采用了(小規模)芯片(集成電路)的主流機型,與采用晶體管的第二代計算機相比,性價比有了很大的提高。這些計算機的後代仍在大型的計算機中心裏使用,此乃現在服務器的前身,這些服務器每秒處理不小於千次的請求。

如何解決第二代計算機的問題1:
卡片被拿到機房後能夠很快的將作業從卡片讀入磁盤,於是任何時刻當一個作業結束時,操作系統就能將一個作業從磁帶讀出,裝進空出來的內存區域運行,這種技術叫做
同時的外部設備聯機操作:SPOOLING,該技術同時用於輸出。當采用了這種技術後,就不在需要IBM1401機了,也不必將磁帶搬來搬去了(中間倆小人不再需要)

如何解決第二代計算機的問題2:

第三代計算機的操作系統廣泛應用了第二代計算機的操作系統沒有的關鍵技術:多道技術

cpu在執行一個任務的過程中,若需要操作硬盤,則發送操作硬盤的指令,指令一旦發出,硬盤上的機械手臂滑動讀取數據到內存中,這一段時間,cpu需要等待,時間可能很短,但對於cpu來說已經很長很長,長到可以讓cpu做很多其他的任務,如果我們讓cpu在這段時間內切換到去做其他的任務,這樣cpu不就充分利用了嗎。這正是多道技術產生的技術背景

多道技術:

多道技術中的多道指的是多個程序,多道技術的實現是為了解決多個程序競爭或者說共享同一個資源(比如cpu)的有序調度問題,解決方式即多路復用,多路復用分為時間上的復用和空間上的復用。

空間上的復用:將內存分為幾部分,每個部分放入一個程序,這樣,同一時間內存中就有了多道程序。

技術分享圖片

時間上的復用:當一個程序在等待I/O時,另一個程序可以使用cpu,如果內存中可以同時存放足夠多的作業,則cpu的利用率可以接近100%,類似於我們小學數學所學的統籌方法。(操作系統采用了多道技術後,可以控制進程的切換,或者說進程之間去爭搶cpu的執行權限。這種切換不僅會在一個進程遇到io時進行,一個進程占用cpu時間過長也會切換,或者說被操作系統奪走cpu的執行權限)

技術分享圖片
現代計算機或者網絡都是多用戶的,多個用戶不僅共享硬件,而且共享文件,數據庫等信息,共享意味著沖突和無序。

操作系統主要使用來

1.記錄哪個程序使用什麽資源

2.對資源請求進行分配

3.為不同的程序和用戶調解互相沖突的資源請求。

我們可將上述操作系統的功能總結為:處理來自多個程序發起的多個(多個即多路)共享(共享即復用)資源的請求,簡稱多路復用

多路復用有兩種實現方式

1.時間上的復用

當一個資源在時間上復用時,不同的程序或用戶輪流使用它,第一個程序獲取該資源使用結束後,在輪到第二個。。。第三個。。。

例如:只有一個cpu,多個程序需要在該cpu上運行,操作系統先把cpu分給第一個程序,在這個程序運行的足夠長的時間(時間長短由操作系統的算法說了算)或者遇到了I/O阻塞,操作系統則把cpu分配給下一個程序,以此類推,直到第一個程序重新被分配到了cpu然後再次運行,由於cpu的切換速度很快,給用戶的感覺就是這些程序是同時運行的,或者說是並發的,或者說是偽並行的。至於資源如何實現時間復用,或者說誰應該是下一個要運行的程序,以及一個任務需要運行多長時間,這些都是操作系統的工作。

2.空間上的復用

每個客戶都獲取了一個大的資源中的一小部分資源,從而減少了排隊等待資源的時間。

例如:多個運行的程序同時進入內存,硬件層面提供保護機制來確保各自的內存是分割開的,且由操作系統控制,這比一個程序獨占內存一個一個排隊進入內存效率要高的多。

有關空間復用的其他資源還有磁盤,在許多系統中,一個磁盤同時為許多用戶保存文件。分配磁盤空間並且記錄誰正在使用哪個磁盤塊是操作系統資源管理的典型任務。

這兩種方式合起來便是多道技術
詳解

空間上的復用最大的問題是:程序之間的內存必須分割,這種分割需要在硬件層面實現,由操作系統控制。如果內存彼此不分割,則一個程序可以訪問另外一個程序的內存,

首先喪失的是安全性,比如你的qq程序可以訪問操作系統的內存,這意味著你的qq可以拿到操作系統的所有權限。

其次喪失的是穩定性,某個程序崩潰時有可能把別的程序的內存也給回收了,比方說把操作系統的內存給回收了,則操作系統崩潰。

第三代計算機的操作系統仍然是批處理

許多程序員懷念第一代獨享的計算機,可以即時調試自己的程序。為了滿足程序員們很快可以得到響應,出現了分時操作系統

如何解決第二代計算機的問題3:

分時操作系統:
多個聯機終端+多道技術

20個客戶端同時加載到內存,有17在思考,3個在運行,cpu就采用多道的方式處理內存中的這3個程序,由於客戶提交的一般都是簡短的指令而且很少有耗時長的,索引計算機能夠為許多用戶提供快速的交互式服務,所有的用戶都以為自己獨享了計算機資源

CTTS:麻省理工(MIT)在一臺改裝過的7094機上開發成功的,CTSS兼容分時系統,第三代計算機廣泛采用了必須的保護硬件(程序之間的內存彼此隔離)之後,分時系統才開始流行

MIT,貝爾實驗室和通用電氣在CTTS成功研制後決定開發能夠同時支持上百終端的MULTICS(其設計者著眼於建造滿足波士頓地區所有用戶計算需求的一臺機器),很明顯真是要上天啊,最後摔死了。

後來一位參加過MULTICS研制的貝爾實驗室計算機科學家Ken Thompson開發了一個簡易的,單用戶版本的MULTICS,這就是後來的UNIX系統。基於它衍生了很多其他的Unix版本,為了使程序能在任何版本的unix上運行,IEEE提出了一個unix標準,即posix(可移植的操作系統接口Portable Operating System Interface)

後來,在1987年,出現了一個UNIX的小型克隆,即minix,用於教學使用。芬蘭學生Linus Torvalds基於它編寫了Linux

第四代計算機(1980~至今):個人計算機

PS:即使可以利用的cpu只有一個(早期的計算機確實如此),也能保證支持(偽)並發的能力。將一個單獨的cpu變成多個虛擬的cpu(多道技術:時間多路復用和空間多路復用+硬件上支持隔離),沒有進程的抽象,現代計算機將不復存在。

技術分享圖片
#一 操作系統的作用:
    1:隱藏醜陋復雜的硬件接口,提供良好的抽象接口
    2:管理、調度進程,並且將多個進程對硬件的競爭變得有序

#二 多道技術:
    1.產生背景:針對單核,實現並發
    ps:
    現在的主機一般是多核,那麽每個核都會利用多道技術
    有4個cpu,運行於cpu1的某個程序遇到io阻塞,會等到io結束再重新調度,會被調度到4個
    cpu中的任意一個,具體由操作系統調度算法決定。
    
    2.空間上的復用:如內存中同時有多道程序
    3.時間上的復用:復用一個cpu的時間片
       強調:遇到io切,占用cpu時間過長也切,核心在於切之前將進程的狀態保存下來,這樣
            才能保證下次切換回來時,能基於上次切走的位置繼續運行
並發的理論基礎

python3全棧開發-補充UDP的套接字、操作系統、並發的理論基礎