1. 程式人生 > 其它 >Linux多程序開發IV

Linux多程序開發IV

1.共享記憶體。允許兩個或多個程序共享實體記憶體的同一塊區域(段)。
  • 共享記憶體是程序使用者空間的一部分,因此這種IPC機制需要更少的核心處理。一個程序將資料複製到共享記憶體中,那麼這部分資料就會對其他所有共享同一個段的程序可用。
  • 與管道等要求傳送程序將資料從使用者空間的緩衝區複製到核心記憶體和接收程序將資料從核心記憶體複製進使用者空間的緩衝區的做法相比,這種IPC技術速度更快。
2.共享記憶體的使用步驟。
  • 呼叫shmget()建立一個新共享記憶體段或取得一個已有的共享記憶體段的識別符號。返回共享記憶體識別符號。
  • 使用shmat()附上共享記憶體,即使該段成為呼叫程序的虛擬記憶體的一部分。
  • 此刻在程式中可以像對待其他可用記憶體那樣對待該共享記憶體段。可以使用shmat()呼叫返回的addr值(指向程序的虛擬地址空間中該共享記憶體段的起點的指標)來引用共享記憶體。
  • 呼叫shmdt()分離共享記憶體段。
  • 呼叫shctl()刪除共享記憶體段。只有噹噹前所有附加記憶體段的程序都與之分離之後記憶體段才會銷燬。只有一個程序需要執行這一步。
3.相關函式。
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget(ket_t key, size_t size, int shmflg);
    - 作用:建立一個新的共享記憶體段,或者獲取一個既有的共享記憶體段的標識
    - key: 標識共享記憶體,16進位制,非0
    - size: 共享記憶體大小
    - shmflg: 共享記憶體的屬性,訪問屬性,附加屬性:建立/判斷共享記憶體是否存在,IPC_CREAT 建立;IPC_EXCL 判斷共享記憶體是否存在,與IPC_CREAT一起使用;e.g.: IPC_CREAT | IPC_EXCL | 0664
    - 返回值:成功返回>0 表示共享記憶體的引用的ID,失敗返回-1並設定errno
 
void *shmat(int shmid, const void *shmadd, int shmflg);
    - 作用:和當前程序進行關聯
    - shmid: 共享記憶體的標識,由shmget返回值獲取
    - shaddr: 申請的共享記憶體起始地址,指定NULL,由核心指定
    - shmflg: 對共享記憶體的操作,SHM_EXEC 執行;SHM_RDONLY 只讀;0 讀寫許可權
    - 返回值:成功返回共享記憶體的首地址,失敗返回(void*)-1
 
int shmdt(const void *shaddr);
    - 作用:解除當前程序和共享記憶體的關聯
    - shmaddr: 共享記憶體的首地址
    - 返回值:成功返回0,失敗返回-1
 
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    - 作用:對共享記憶體進行操作。刪除共享記憶體,共享記憶體要刪除才會消失,建立共享記憶體的程序被銷燬對共享記憶體沒有影響
    - shmid: 共享記憶體的id
    - cmd: 要做到操作,IPC_STAT: 獲取共享記憶體的當前狀態;IPC_SET:設定共享記憶體的狀態;IPC_RMID: 標記共享記憶體被銷燬
    - buf: 需要設定或者獲取的共享記憶體的屬性資訊,IPC_STAT: buf儲存資料;IPC_SET:buf中需要初始化資料,設定到核心中;IPC_RMID:沒有用,NULL
 
#include <sys/typre.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
    - 作用:根據指定的路徑名,和int值,生成一個共享記憶體的key
    - pathname: 制定一個存在的路徑
    - proj_id: int型別,系統呼叫只會使用其中的1個位元組,0-255,一般指定一個字元'a'
4.共享記憶體相關問題。
  • 作業系統如何知道共享記憶體被多少程序關聯?
-共享記憶體維護了一個結構體struct shmid_ds,這個結構體有一個成員 shm_nattch記錄裡關聯程序的個數。
  • 可不可以對共享記憶體多次刪除? shmctl
-可以,因為shmctl只是標記刪除共享記憶體,不是直接刪除。只有當和共享記憶體關聯的程序數為0時才會被真正刪除。當共享記憶體的key位0時,表示共享記憶體被標記刪除。 5.共享記憶體和記憶體對映的區別。
  • 共享記憶體可以直接建立,記憶體對映需要磁碟檔案(匿名對映除外)
  • 共享記憶體效率更高
  • 共享記憶體:所有程序操作的是同一塊共享記憶體。記憶體對映:每個程序在自己的虛擬地址空間中有一個獨立的記憶體
  • 資料安全:
    • 程序突然退出:共享記憶體還存在,記憶體對映區消失
    • 執行程序的電腦宕機或宕機:資料存在共享記憶體中的沒有了;記憶體對映區的資料,由於磁碟檔案中的資料還在,所有記憶體對映區的資料還存在
  • 生命週期:
    • 共享記憶體:程序退出,共享記憶體還在,標記刪除(所有關聯的程序數為0才會刪除)或者關機。如果一個程序退出,會自動和共享記憶體取消關聯。
    • 記憶體對映區:程序退出,記憶體對映區銷燬
6.共享記憶體操作命令。
ipcs -a            列印所有程序通訊方式
     -m            列印使用共享記憶體進行程序通訊的資訊
     -q            列印使用訊息佇列進行程序通訊的資訊
     -s            列印使用訊號進行程序通訊的資訊
 
 
ipcrm -M shmkey    使用shmkey移除建立的共享記憶體段
ipcrm -m shmid     使用shmid移除標識的共享記憶體段
ipcrm -Q msgkey    使用msgkey移除建立的訊息佇列
ipcrm -q msgid     使用msgkey移除標識的訊息佇列
ipcrm -S semkey    使用semkey移除建立的訊號
ipcrm -s semid     使用emkey移除標識的訊號

  

7.控制終端。
  • 使用者通過終端登入系統後得到shell程序,這個終端就是該shell程序的控制終端。
  • 控制終端是儲存在PCB中的資訊,由該shell程序啟動的其它進城的控制終端也是該終端。
  • 預設情況下,每個程序的標準輸入、輸出、錯誤都指向控制終端。程序從標準輸入讀就是讀使用者鍵盤輸入,程序往標準輸出寫就是輸出到顯示器上。
  • 在控制終端輸入特殊的控制鍵可以給前臺程序傳送訊號。無法給後臺程序傳送訊號(&結尾)。
$ tty            檢視控制終端的裝置
$ each $$        檢視當前終端的程序號
8.程序組。
  • 程序組是一組相關程序的集合。
  • 程序組識別符號(PGID)。
  • 程序組擁有一個生命週期,開始時間是首程序建立組的時刻,結束時間是最後一個成員程序退出組的時刻。程序組首程序無需是最後一個離開程序組的成員。
9.會話。
  • 會話是一組相關程序組的集合。會話首程序是建立該新會話的程序,其程序ID成為會話ID。新程序會繼承其父程序的會話ID。
  • 一個會話中的所有程序共享單個控制終端。控制終端在會話首程序首次開啟終端裝置室被建立,一個終端最多會成為一個會話的控制終端。
  • 任一時刻,會話中其中一個程序組成為終端的前臺程序組,其他程序組會成為後臺程序組。只有前臺程序組中的程序才能從控制終端讀取資料。
  • 控制終端連線建立以後,會話首程序成為該終端的控制程序。
10.程序組、會話、控制終端之間的關係。
find / 2 > /dev/null | wc -l &
sort < longlist | uniq -c
11.程序組、會話操作函式。
pid_t getpgrp(void);
pid_t getpgid(pid_t pid);
int setpgid(pid_t pid, pid_t pgid);
pid_t getsid(pid_t pid);
pid_t setsid(void);
12.守護程序(DaemonProcess 精靈程序)。
  • Linux中的後臺服務程序。生存期較長,通常獨立於控制終端並且週期性執行某種任務或等待處理某些發生的事件。以d結尾。
  • 特點:
    • 生命週期很長,守護程序會在系統啟動時被建立並一直執行直至系統關閉。
    • 在後臺執行並且不擁有控制終端。沒有控制終端確保了核心永遠不會為守護程序自動生成任何控制訊號和終端訊號。
  • e.g.: Linux的大多數伺服器是守護程序實現的。Internet伺服器 inetd,Web伺服器 httpd等。
13.守護程序的建立步驟。
  1. 執行一個fork(),父程序退出,子程序繼續執行。(必須)
  2. 子程序呼叫setid()開啟一個新的會話。(必須)
  3. 使用umask(0)清除程序的umask以確保守護程序建立檔案和目錄時擁有許可權。
  4. 修改程序的當前工作目錄,改為根目錄(/)。
  5. 關閉守護程序從父程序繼承而來的所有開啟的檔案描述符。
  6. 關閉檔案描述符0,1,2之後,守護程序開啟/dev/null並使用dup2()使所有這些描述符指向這個裝置。
  7. 核心業務邏輯。(必須)