LinuxAPP學習筆記---持續更新

1、APP對於底層設備的操作

APP對於底層設備的讀寫操作,最穩妥的方式是使用select模式讀寫,不建議使用在主循環中輪詢的方式來讀取數據。在主循環中對設備數據進行讀寫對輪詢的時間間隔比較敏感,比如串口慢速設備,如果在輪詢中沒有延時,就會一直導致讀不出數據,因爲內核中驅動是使用信號量的方式監聽數據,APP發起的讀操作幾乎沒有時間間隔的話,會導致信號量永遠沒有機會返回。


2、對於TCP連接的維護。阻塞方式
   服務器端可以通過監聽收到數據是否爲0來實現。客戶端也可以通過監聽收到數據是否爲0實現。
   但是區別是,客戶端在連接服務器端之前,無法判斷服務器端是否ok;服務器端在監聽客戶端之前,
   可以通過服務器的socket句柄來判斷是否可以建立客戶端監聽。
  非阻塞方式,可以通過receive返回的錯誤碼來判定是否斷開

3、線程間和進程間通信方式簡介

(1)管道(Pipe):管道可用於具有親緣關係進程間的通信,允許一個進程和另一個與它有共同祖先的進程之間進行通信。
(2)命名管道(named pipe):命名管道克服了管道沒有名字的限制,因此,除具有管道所具有的功能外,它還允許無親緣關係進程間的通信。命名管道在文件系統中有對應的文件名。命名管道通過命令mkfifo或系統調用mkfifo來創建。
(3)信號(Signal):信號是比較複雜的通信方式,用於通知接受進程有某種事件發生,除了用於進程間通信外,進程還可以發送信號給進程本身;linux除了支持Unix早期信號語義函數sigal外,還支持語義符合Posix.1標準的信號函數sigaction(實際上,該函數是基於BSD的,BSD爲了實現可靠信號機制,又能夠統一對外接口,用sigaction函數重新實現了signal函數)。
(4)消息(Message)隊列:消息隊列是消息的鏈接表,包括Posix消息隊列system V消息隊列。有足夠權限的進程可以向隊列中添加消息,被賦予讀權限的進程則可以讀走隊列中的消息。消息隊列克服了信號承載信息量少,管道只能承載無格式字節流以及緩衝區大小受限等缺
(5)共享內存:使得多個進程可以訪問同一塊內存空間,是最快的可用IPC形式。是針對其他通信機制運行效率較低而設計的。往往與其它通信機制,如信號量結合使用,來達到進程間的同步及互斥。
(6)內存映射(mapped memory):內存映射允許任何多個進程間通信,每一個使用該機制的進程通過把一個共享的文件映射到自己的進程地址空間來實現它。
(7)信號量(semaphore):主要作爲進程間以及同一進程不同線程之間的同步手段。
(8)套接口(Socket):更爲一般的進程間通信機制,可用於不同機器之間的進程間通信。起初是由Unix系統的BSD分支開發出來的,但現在一般可以移植到其它類Unix系統
上:Linux和System V的變種都支持套接字。

(9)條件變量(Conditions):如果現在在等待一個信號。如果該信號被設置,則繼續運行。如果沒有條件變量,我們將會不停的去查詢該信號是否被設置,這樣就會浪費大量的cpu。而通過使用條件變量,我們就可以將等待信號的線程阻塞,直到有信號的時候再去喚醒它。條件變量最大的好處就是可以使等待條件的線程處於阻塞而不是忙等待狀態。其實使用線程間全局變量共享的方法也可以達到線程間同步的目的,但是缺點就是需要忙等待,耗用CPU資源,並且爲了支持多線程,也必須加互斥鎖保護。

4、pthread_create()在使用的過程中遇到的一個問題:

 今天在使用線程的時候出現了一個問題,利用valgrind監測程序的運行時出現了memory leak。感覺到很奇怪,這樣的情況應該不會發生的啊,畢竟是系統的函數。去網上搜了下,發現國內國外都有這個問題 呵呵。大概瞭解了下原因:創建的線程需要進行join或者detach狀態,這樣才能保證創建線程過程中分配的內存得以釋放,才能避免memory leak的情況。因此,記得需要將線程進行join或者detach。

       線程的分離狀態決定一個線程以什麼樣的方式來終止自己。線程的默認屬性是非分離狀態,這種情況下,原有的線程等待創建的線程結束。只有當pthread_join()函數返回時,創建的線程纔算終止,才能釋放自己佔用的系統資源。而分離線程不是這樣子的,它沒有被其他的線程所等待,自己運行結束了,線程也就終止了,馬上釋放系統資源。程序員應該根據自己的需要,選擇適當的分離狀態。

有以下的方法來解決這個問題:

  1. 1、創建線程,使用默認的非分離狀態,然後進行join

pthread_create(&threadid, NULL, func, NULL);

pthread_join(threadid, &state);

  • 2、創建線程時利用pthread_attr_setdeatchstate()指定線程的屬性爲PTHREAD_CREATE_DETACHED

pthread_attr_t attr;

pthread_attr_init(&attr);

pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

pthread_create(&threadid, &attr, func, NULL);

pthread_attr_destroy(&attr);

    • 3、在默認創建完進程後,使用pthread_detach函數,使得線程處於detach狀態;或者在func中調用pthread_detach函數,線程自行退出

pthread_create(&threadid, NULL, func, NULL);

pthread_detach(threadid);

或者:

pthread_create(&threadid, NULL, func, NULL);

void* func(void*)

{

pthread_detach(pthread_self());

return ((void*)0);

}

5、關於多線程編程中,頻繁調用system函數,會導致segment fault出錯;經過實際測試發現可以通過使用管道的方式(popen,但是要記得pclose)執行sh腳本,並且不會導致調用進程異常:

linux下使用多線程的fork和system會出現問題

根據我的經驗,linux下使用pthread庫寫多線程程序時,在調用系統調用/庫函數方面,應注意至少如下幾點:

1、創建了線程後,不要再使用fork()/vfork()創建子進程

2、儘量不使用signal機制

3、...

 關於1,有個具體的教訓。我實現了一個動態庫,該庫的功能在一個獨立線程裏運行。同事A實現了另一個動態庫,庫的功能在也一個獨立線程裏運行。這兩個庫需要訪問一設備,該設備只支持一個使用者訪問,因此有個全局的信號量,來保證這兩個線程能交替的訪問該設備。我們的測試代碼表明這兩個庫可以正常的配合工作。然後這兩個庫被交給同事B,集成到他的應用程序裏。問題出現了,只要我和A的線程同時運行,幾乎必然出現同時訪問設備的錯誤情況,似乎用來保護的信號量失敗了。多次檢查庫的代碼,沒有發現問題。偶然間,發現同事B的代碼調用了system(),把system()調用替換成相應的代碼實現,問題消失。原因在於system()實際上調用了fork()/vfork()。

爲什麼在多線程調用fork會出現問題呢?我分析是因爲fork會把當前進程複製到子進程,子進程也是多線程。注意在子進程執行fork()-exec()這段時間,子進程的其他線程也在運行,同時信號量也被複制到子進程中。因爲父子進程有獨立的信號量來保護設備,這樣父進程訪問設備的時候,子進程也可以訪問設備,於是出現問題。

  linux下創建子進程和多線程衝突的根本原因在於fork會複製當前進程,而Windows創建子進程就沒有這個問題。爲什麼會這樣呢?個人認爲可能是歷史原因造成的。早期的unix注意是作爲服務器使用,例如web/ftp服務等。在沒有多線程支持的年代,服務器支持多用戶訪問支持的方法就是爲每個用戶創建一個服務子進程。服務子進程通常就是服務器本身,因此提供一個fork調用,是可以提高效率的。但是當初設計fork調用的時候,並沒有考慮到多線程,導致與多線程衝突。unix的歷史負擔很多,比如線程局部存儲(TLS),個人認爲就是爲了解決早期程序設計者喜歡大量使用全局變量和多進程提出的。

 那如果確實需要在多線程程序裏運行另一個程序(而且只有可執行文件沒有源代碼)怎麼辦呢?可以把要執行的程序包裝一下,多線程的主程序通過進程間通信的方式包裝後的子進程通信。

 與關於第2點多線程與signal機制的問題,網上很多,大家搜索一下就有了,不多說了

6、core dump使用

//設置生成core dump文件有pid後綴

echo "1" > /proc/sys/kernel/core_uses_pid
//設置core dump文件大小無限制
ulimit -c unlimited
//設置core dump文件生成目錄
echo "/corefile/core-%e-%p-%t" >core_pattern

7、TCP編程經驗-CLIENT

a、如果是客戶端從來沒有connect過server,那recv函數返回的是-1,如果曾經connect過server,但是server斷開,那麼recv返回的是0,並且該
   情況下如果不關閉socket並重新建立的話,connect函數會返回失敗(無論server是否啓動)。






8、TCP編程經驗-SERVER





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章