1. 程式人生 > >Linux系統程式設計學習筆記

Linux系統程式設計學習筆記

PDB的常用的除錯命令:

程式先寫完的情況的呼叫方式:

1、 python3  -m pdb test.py

 #斷點的過程  b 7     ## 後面的數字是 行數

 ## = 清楚斷點的時候   clear 7  ## 後面的是數字行數

2、其他的一些指令

  PyCharm,常用的IDE。

3、r ----> return   快速執行到函式的最後一行

 4、還有一種互動式的呼叫方式

5、 伺服器不停止的情況下,用日誌除錯法。

  1. 第三個視訊 pep8規則

1、

2、函式和類 之間一般用兩個空格隔絕愛,類與類之間一個空格

3、Python3 預設 UTF-8,不應有編碼宣告。

4、想在一行程式碼裡放兩條語句,用分號隔開。

  1. 第五個視訊  多工的理解

1、單核CPU可以同時執行好多的程式的原因是: 利用的時間片輪轉、優先順序排程。

2、  並行

        併發       兩個詞彙的理解,一般我們的電腦都是併發的型別。

程序的建立-fork

1、 import  os

       ret = os.fork()       # linux中才有的東西

2、 

   如圖所示就會完成, if 和else 裡面的內容一起執行。

3、父程序建立子程序,但是誰先執行還不一定        

4、 ret 這個值是多少?    建立一個子程序,自己本身是一個大於0的值,另一個子程序等於0

      用 cat  加上程式碼程式.py   就可以在命令列檢視程式碼

os.getpid()  獲取自己的PID,,os.ppid()-- 獲取自己父親的PID                                                    

08父子程序的先後順序

1、只要主程序執行完畢,就可以列印系統提示

    for example:   多工,加快程式的執行

09全域性變數在多個子程序中 不共享

1、 全域性變數在一個程序中修改,在另一個程序沒有影響

10多次fork問題

1、  fork炸彈:

         while  true:

                os.fork()       # 不要隨便執行這個程式碼,一下子就崩潰

12 Process 建立程序 --- 跨平臺的寫法

1、以後寫建立子程序的方式,不用fork的方式,用這種可以跨平臺的方式來寫

13 主程序等待Process裡的子程序先結束

1、主程序要等待著 所有的子程序先結束才會over,,兒子孫子都執行完之後才能自己結束!0

14 join 子程序

1、join()⽅法可以等待⼦程序結束後再繼續往下運⾏, 通常⽤於程序間的同

  for example:

 等待 子程序結束以後在去列印 “----main----” 這個主程序的東西

   主程序等待著 子程序的執行,一直在 p.join( ) 這裡等待著,稱為 堵塞 狀態。

    ## 函式說明裡面帶有 中括號的,就是意味著 可寫可不寫的狀態。

    join([ timeout])    timeout : 等待的最長的時間。

2、p.terminate   不管任務是否完成,立即終止

15  Process 子程序

1、計算執行程式所花的時間:

      import  time

      time.time()    ##  呼叫time裡面的time()方法,通過兩個時間相減就可以得到程式執行所需要的時間。

2、

程式中,,當 定義一個是實際類後,執行 p.start() ,會首先進入 start()方法裡面進行執行,這個方法裡面蘊含著呼叫  run方法,呼叫run方法之後,建立的子程序就會 執行run()方法

    如果在後面給主程式加上兩句程式碼如下:

      while(true)

             print("-----main-----")

             time.sleep(1)

    相應的子程序和主程序就會同時執行兩個列印過程, 一個列印 -----1----   另一個列印 ----main----- 方法。

16  程序池   -- 非常簡單的一種 建立 程序的方法

1、  第一點,先匯入:   from  multiprocessing import  Pool

                                       import os,time,random

   po = Pool(3)  # 定義一個程序,最大的程序數是 3

10個任務交給3個小弟去做, 所以只有先安排的任務做完了,才會有新的程序進入到程序池裡面。

 重點需要說的一點: pool.apply_async(worker,(i,))

    pool.close    # 關閉程序池,相當於 不能夠再次新增新任務了

    pool.join()    #

17 建立 程序的總結

1、   ret = os.fork()    #  儘量不要用,非常底層

2、  Process (target = xxxx)

       p1.start()

   ## 通過建立子類來建立 程序

3、 建立程序池,,,推薦使用

    # 主程序一般用來等待,真正的任務一般都在子程序中執行

      pool = Pool (3)   # 經過壓力測試,得出一個合適的值。

      pool.apply_async(xxxx)

18  堵塞式新增任務

1、

圖中紅色箭頭的地方,實際上,當繼續執行的時候, 打印出來一個數字,然後建立一個子程序,當去執行子程序的時候,主程式就會卡在原來的位置不變,等到上一個任務執行完之後才會繼續新增新任務。  幾乎不用的一種方式。

19  程序間的通訊- Queue (  佇列 )

1、對於佇列來說是    先進先出

        還有就是  定義一個佇列應該這麼定義:    p = Queue(x)   # 裡面的 x 代表隊列的大小,如果不寫的話,意味著你這個佇列想要多大都可以,自己隨意。

2、 常用的一些方法

     佇列可以填充任何的東西,任何東西都是可以往裡面新增的

3、q.get_nowait()

     q.put_nowait()     不需要等待,或者以另外一種方式告訴你  佇列已經空了,或者已經滿了不能存放其他資料了。

4、程序池中的Queue

     程序池中的通訊和普通程序之間的通訊大致是一樣的,但是需要做兩點

      (1)、匯入一個模組   from multiprocessing import Manager, Queue

 換成 Manager 的形式!

(2)、 以下是兩種 利用佇列進行通訊的對比

(3)程序池中的通訊

程序與程序之間預設是沒有聯絡的,,要想聯絡到一起,其中一種方法就是 佇列。

二、多執行緒  (Linux系統程式設計)

1、使用Thread 完成多執行緒任務

   1、python 中的一個  Threading 模組,能夠很好的實現多執行緒的任務。

           最簡單的例子:      

 threading模組中的 Thread 函式和上一節課所學的  Process 模組類似,用法也類似,可以實現同時列印五句話。

程序是資源分配的單位,執行緒是CPU排程的單位。在同一個程序裡面完成建立多個執行緒,進而進行運算,這樣的方案能夠在現有資源的基礎上,實現更高的效率。

 綠色的稱之為 主執行緒,當主執行緒執行到 Thread(target = test ),這句話是,就會建立一個額外的子執行緒(紅顏色的箭頭),子執行緒從哪裡執行,實際上已經規定好了,就是從 test 開始執行。  主執行緒在這裡其實只是執行了5次for迴圈,真正列印東西的是  主執行緒生成的5個子執行緒。

2、使用Thread子類完成建立多執行緒

1、多個執行緒執行一個函式的時候,各自之間不會有影響,各是各的。

2、建立執行緒的新辦法:

 

 建立一個自己的類,以 Thread作為自己的基類,然後將自己要實現的東西放在 類裡面的 run方法裡面。  

    當後面,創造一個例項之後,執行 t.start() 時,在start方法裡面有一個呼叫 run方法的隱藏,所以就會直接呼叫 run方法,進而直接執行 類裡面的方法。

3、執行緒的執行順序

1、

 當執行完建立執行緒任務時,這時候有6個執行緒等待著作業系統去排程,所以這時候誰先被執行呢? 執行順序和你執行執行緒沒有太大的關係,作業系統說了算!

4、執行緒共享全域性變數

1、  程序: 不管全域性變數還是區域性變數,統統都是個人是個人的,互相之間沒有影響。

        執行緒:  執行緒之間共享全域性變數。

5、 執行緒共享全域性變數的問題

 (視訊出現了問題,播放不了,找一下其他地方的視訊補上 )

1、   這種方式  可以解決   之間的通訊。

        執行緒共享全域性變數,就會有一些弊端存在!

      

6、 列表當作實參傳遞執行緒處理函式中

1、

  將一個列表當作是一個引數傳遞到函式裡面的時候也是可以共享的, 多執行緒共享全域性變數。

7、程序和執行緒的對比

1、

   為什麼最後的結果不是 200w次呢?

   作業系統每一次只能執行一句程式,所以當一個程式還沒執行完的時候,就已經被趕出來了,所以出現了很多的重疊,所以不是200w次。

8、避免全域性變數被修改的方式

1、上面的例子修改的方式:

       第一種方法就是: 使用  sleep,讓其中的一個程序進行執行,當執行完之後在繼續執行下一個程序,這樣就不會出現這種問題了。

2、

這種方案也非常不錯,輪詢的方式執行!

9、互斥鎖

1、建立互斥鎖

具體上鎖:

threading.Lock(   )    # 裡面有兩個重要的引數,第一個 blocking 預設為 true:詢問一下是否堵塞。

  第二個引數是, timeout ,設定一下執行的時間,預設為 -1,無限等待。

對於上面的程式碼出現的問題,用互斥鎖來解決的方法:

優點: 當一個程序因為沒有搶到上鎖而停滯的時候,它不佔用CPU,所以相對來說,效率就會變高。

10、大家遇到的問題 (還沒有看,明天繼續看!)

1、 將上鎖放在 for迴圈裡面,這樣的話,導致一種現象就是, 每一次執行for迴圈的時候,兩個迴圈裡面都在競爭上鎖,降低效率。

 什麼時候加鎖?  上鎖的程式碼越少越好。 為什麼不是100w,因為每次都在搶著上鎖,所以不確定執行的次數。

11、多執行緒使用非共享變數

1、 threading 模組當中的 current_thread()方法 的名字就是當前執行緒裡面的名字。

2、雖然兩個執行緒都到同一個函式裡面去執行,但是個人是個人的變數,互相不影響。

     去看一下文件裡面的程式碼,然後反思一下。

12、死鎖以及解決辦法

1、看門狗 的原理,,新增一個變數。

13、同步的理解已經使用

1、同步就是協同步調,按預定的先後次序進行執行。 非同步: 不確定先後的順序。

2、用 互斥鎖實現“同步” 的方法:

14、生產者與消費者來解決耦合問題

                 解耦在寫程式碼的過程中非常重要!

1、 第一個匯入佇列模組:(佇列: 先進先出 )

      python3 中應該這麼寫:  from queue import Queue 

      python2 中應該這麼寫:  from Queue import Queue

2、 執行緒中的佇列建立方式:  queue = Queue( )

              ----- 佇列的基本操作: queue.put()   queue.get()    queue.qsize()   queue.put_nowait()

      生產者與消費者之間的關係的一個完整的程式碼形式:

 佇列就是用來 給 生產者和消費者之間解耦用的

15、ThreadLocal物件線上程中的使用

1、使用全域性字典的方法

   這種方案可以實現,但是非常的費勁,所以下一種方法應運而生

2、ThreadLocal 方法

    當兩個執行緒都需要對全域性變數進行操作的時候,就可以聯想這個ThreadLocal 方法的使用。

         對屬性設定一個值,這一點需要自己課下好好的回顧一下

 

15、非同步的實現

1、實現程式碼好好看看

非同步: 就是當我正在做著某件事情的時候,突然通知我去做其他的事情, 這種情況叫做 非同步。

    上述程式碼的原理:

     1)、 主程序一直在睡覺,當 子程序執行完畢的時候,主程序醒來,直接去執行 test2 ,, 子程序在結束的時候,會傳遞一個  “hahaha” 給test2(主程序), 這種情況叫做 非同步。

      2)、 定義一個 執行緒池,,  然後呼叫   pool.apply_async( func = test,callback = test2): 這句程式碼的解釋是:   前面的 func = test,就相當於直接寫 一個 test,, 後面的 callback 意思是 回撥,主程序去幹的事情。

16、GIL的問題 ---  全域性直譯器鎖

1、 多程序的效率明顯大於 多執行緒的效率, 對於單核來說沒必要,但是對於多核來說 至關重要。

2、 如何解決這個問題呢?

       接下來首先需要了解一下的是, 如何在Ubuntu系統中寫C語言程式:

        以後在開發的過程中,無論是從網上當下來一個 C語言程式還是其他的,首先都要去重視一下 read.me 檔案,用程式碼  cat  read.me   就可以讀出來該 C語言程式應該如何執行以及執行在什麼環境下。 切記這一點!

     克服Python中死迴圈的問題:   死迴圈用C語言來寫,這樣能使得程式的執行效率達到很高的程度。