1. 程式人生 > 實用技巧 >Cent OS7強制安裝Mysql8.0.22的錯誤解決辦法

Cent OS7強制安裝Mysql8.0.22的錯誤解決辦法

一.概念說明

在進行解釋之前,首先要說明幾個概念:

使用者空間和核心空間

程序切換

程序的阻塞

檔案描述符

快取 IO

使用者空間與核心空間

現在作業系統都是採用虛擬儲存器,那麼對32位作業系統而言,它的定址空間(虛擬儲存空間)為4G(2的32次方)。作業系統的核心是核心,獨立於普通的應用程式,可以訪問受保護的記憶體空間,也有訪問底層硬體裝置的所有許可權。為了保證使用者程序不能直接操作核心(kernel),保證核心的安全,作業系統將虛擬空間劃分為兩部分,一部分為核心空間,一部分為使用者空間。針對linux作業系統而言,將最高的1G位元組(從虛擬地址0xC0000000到0xFFFFFFFF),供核心使用,稱為核心空間,而將較低的3G位元組(從虛擬地址0x00000000到0xBFFFFFFF),供各個程序使用,稱為使用者空間。

使用者空間<------------->核心空間<------------->裝置空間

程序切換

為了控制程序的執行,核心必須有能力掛起正在CPU上執行的程序,並恢復以前掛起的某個程序的執行。這種行為被稱為程序切換。因此可以說,任何程序都是在作業系統核心的支援下執行的,是與核心緊密相關的。

從一個程序的執行轉到另一個程序上執行,這個過程中經過下面這些變化:

儲存處理機上下文,包括程式計數器和其他暫存器。

更新PCB資訊。

把程序的PCB移入相應的佇列,如就緒、在某事件阻塞等佇列。

選擇另一個程序執行,並更新其PCB。

更新記憶體管理的資料結構。

恢復處理機上下文。

注:總而言之切換程序很耗資源。

程序的阻塞##

正在執行的程序,由於期待的某些事件未發生,如請求系統資源失敗、等待某種操作的完成、新資料尚未到達或無新工作做等,則由系統自動執行阻塞原語(Block),使自己由執行狀態變為阻塞狀態。可見,程序的阻塞是程序自身的一種主動行為,也因此只有處於執行態的程序(獲得CPU),才可能將其轉為阻塞狀態。當程序進入阻塞狀態,是不佔用CPU資源的。

檔案描述符fd

檔案描述符(File descriptor)是電腦科學中的一個術語,是一個用於表述指向檔案的引用的抽象化概念。

檔案描述符在形式上是一個非負整數。實際上,它是一個索引值,指向核心為每一個程序所維護的該程序開啟檔案的記錄表。當程式開啟一個現有檔案或者建立一個新檔案時,核心向程序返回一個檔案描述符。在程式設計中,一些涉及底層的程式編寫往往會圍繞著檔案描述符展開。但是檔案描述符這一概念往往只適用於UNIX、Linux這樣的作業系統。

快取 IO

快取 IO 又被稱作標準 IO,大多數檔案系統的預設 IO 操作都是快取 IO。在 Linux 的快取 IO 機制中,作業系統會將 IO 的資料快取在檔案系統的頁快取( page cache )中,也就是說,資料會先被拷貝到作業系統核心的緩衝區中,然後才會從作業系統核心的緩衝區拷貝到應用程式的地址空間。

快取 IO 的缺點:

資料在傳輸過程中需要在應用程式地址空間和核心進行多次資料拷貝操作,這些資料拷貝操作所帶來的 CPU 以及記憶體開銷是非常大的。

二.5種IO模型

阻塞IO模型

最傳統的一種IO模型,即在讀寫資料過程中會發生阻塞現象。當用戶執行緒發出IO請求之後,核心會去檢視資料是否就緒,如果沒有就緒就會等待資料就緒,而使用者執行緒就會處於阻塞狀態,使用者執行緒交出CPU。當資料就緒之後,核心會將資料拷貝到使用者執行緒,並返回結果給使用者執行緒,使用者執行緒才解除block狀態。(阻塞模式下使用者程序需要等待兩次,一次為等待io中的資料就緒,一次是等待核心把資料拷貝到使用者空間)

如果資料沒有就緒,就會一直阻塞在read方法。具體流程如下圖所示:

非阻塞IO模型

  阻塞IO模式有一個缺點是每次io事件沒有就緒時,使用者程序需要一直等待,使得使用者程序需要一直等待。因此引入了非阻塞IO,當用戶執行緒發起一個read操作後,並不需要等待,而是馬上就得到了一個結果。如果結果是一個error時,它就知道資料還沒有準備好,於是就返回到使用者程序去執行其他任務,等過一段時間後在去檢視資料是否準備好。一旦核心中的資料準備好了,並且又再次收到了使用者執行緒的請求,那麼它馬上就將資料拷貝到了使用者執行緒,然後返回。所以事實上,在非阻塞IO模型中,使用者執行緒需要不斷地詢問核心資料是否就緒,也就說非阻塞IO不會交出CPU,而會一直佔用CPU。

典型的非阻塞IO模型一般如下:


while(true)
{
 
   data = socket.read();
 
   if(data!= error)
   {
 
       processData();
 
       break;
   }
   if(data==error)
   {
        run_user_thread();
 
   }
 

但是對於非阻塞IO就有一個非常嚴重的問題,在while迴圈中需要不斷地去詢問核心資料是否就緒,這樣會導致CPU佔用率非常高,因此一般情況下很少使用while迴圈這種方式來讀取資料。

多路複用IO模型

  多路複用IO主要用於處理多個IO連線時候的場景。在多路複用IO模型中,會有一個執行緒不斷去輪詢多個socket的狀態,只有當socket真正有讀寫事件時,才真正呼叫實際的IO讀寫操作。因為在多路複用IO模型中,只需要使用一個執行緒就可以管理多個socket,系統不需要建立新的程序或者執行緒,也不必維護這些執行緒和程序,並且只有在真正有socket讀寫事件進行時,才會使用IO資源,所以它大大減少了資源佔用。

   也許有朋友會說,我可以採用多執行緒+ 阻塞IO 達到類似的效果,但是由於在多執行緒 + 阻塞IO 中,每個socket對應一個執行緒,這樣會造成很大的資源佔用,並且尤其是對於長連線來說,執行緒的資源一直不會釋放,如果後面陸續有很多連線的話,就會造成效能上的瓶頸。

  而多路複用IO模式,通過一個執行緒就可以管理多個socket,只有當socket真正有讀寫事件發生才會佔用資源來進行實際的讀寫操作。因此,多路複用IO比較適合連線數比較多的情況。

  另外多路複用IO為何比非阻塞IO模型的效率高是因為在非阻塞IO中,不斷地詢問socket狀態時通過使用者執行緒去進行的,而在多路複用IO中,輪詢每個socket狀態是核心在進行的,這個效率要比使用者執行緒要高的多。

  不過要注意的是,多路複用IO模型是通過輪詢的方式來檢測是否有事件到達,並且對到達的事件逐一進行響應。因此對於多路複用IO模型來說,一旦事件響應體很大,那麼就會導致後續的事件遲遲得不到處理,並且會影響新的事件輪詢。(注意多路複用io中程序也會有兩次阻塞,相比於非阻塞IO模型多了一次阻塞,因此在實際的應用場景中到底使用那種IO模型,還需要結合場景而定)。

訊號驅動IO模型

  在訊號驅動IO模型中,當用戶執行緒發起一個IO請求操作,會給對應的socket註冊一個訊號函式,然後使用者執行緒會繼續執行,當核心資料就緒時會發送一個訊號給使用者執行緒,使用者執行緒接收到訊號之後,便在訊號函式中呼叫IO讀寫操作來進行實際的IO請求操作。這個一般用於UDP中,對TCP套介面幾乎是沒用的,原因是該訊號產生得過於頻繁,並且該訊號的出現並沒有告訴我們發生了什麼事情

非同步IO模型
    非同步IO模型才是最理想的IO模型,在非同步IO模型中,當用戶執行緒發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從核心的角度,當它受到一個asynchronous read之後,它會立刻返回,說明read請求已經成功發起了,因此不會對使用者執行緒產生任何block。然後,核心會等待資料準備完成,然後將資料拷貝到使用者執行緒,當這一切都完成之後,核心會給使用者執行緒傳送一個訊號,告訴它read操作完成了。也就說使用者執行緒完全不需要關心實際的整個IO操作是如何進行的,只需要先發起一個請求,當接收核心返回的成功訊號時表示IO操作已經完成,可以直接去使用資料了。

  也就說在非同步IO模型中,IO操作的兩個階段都不會阻塞使用者執行緒,這兩個階段都是由核心自動完成,然後傳送一個訊號告知使用者執行緒操作已完成。使用者執行緒中不需要再次呼叫IO函式進行具體的讀寫。這點是和訊號驅動模型有所不同的,在訊號驅動模型中,當用戶執行緒接收到訊號表示資料已經就緒,然後需要使用者執行緒呼叫IO函式進行實際的讀寫操作;而在非同步IO模型中,收到訊號表示IO操作已經完成,不需要再在使用者執行緒中呼叫iO函式進行實際的讀寫操作。

   前面四種IO模型實際上都屬於同步IO,只有最後一種是真正的非同步IO,因為無論是多路複用IO還是訊號驅動模型,IO操作的第2個階段都會引起使用者執行緒阻塞,也就是核心進行資料拷貝的過程都會讓使用者執行緒阻塞。


舉例:

故事情節為:老李去買火車票,三天後買到一張退票。參演人員(老李,黃牛,售票員,快遞員),往返車站耗費1小時。
1.阻塞I/O模型

老李去火車站買票,排隊三天買到一張退票。

耗費:在車站吃喝拉撒睡 3天,其他事一件沒幹

2.非阻塞I/O模型

老李去火車站買票,隔12小時去火車站問有沒有退票,三天後買到一張票。

耗費:往返車站6次,路上6小時,其他時間做了好多事。

3.I/O複用模型

1.select/poll

老李去火車站買票,委託黃牛,然後每隔6小時電話黃牛詢問,黃牛三天內買到票,然後老李去火車站交錢領票。

耗費:往返車站2次,路上2小時,黃牛手續費100元,打電話17次

2.epoll

老李去火車站買票,委託黃牛,黃牛買到後即通知老李去領,然後老李去火車站交錢領票。

耗費:往返車站2次,路上2小時,黃牛手續費100元,無需打電話

4.訊號驅動I/O模型

老李去火車站買票,給售票員留下電話,有票後,售票員電話通知老李,然後老李去火車站交錢領票。

耗費:往返車站2次,路上2小時,免黃牛費100元,無需打電話

5.非同步I/O模型

老李去火車站買票,給售票員留下電話,有票後,售票員電話通知老李並快遞送票上門。

耗費:往返車站1次,路上1小時,免黃牛費100元,無需打電話


ps:理解同步、非同步、阻塞與非阻塞