第8章__進程間通信_第1頁
第8章__進程間通信_第2頁
第8章__進程間通信_第3頁
第8章__進程間通信_第4頁
第8章__進程間通信_第5頁
已閱讀5頁,還剩62頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

www embedu org 本章的要求 第8章 進程間通信掌握Linux中管道的創(chuàng)建和讀寫掌握Linux中有名管道的創(chuàng)建和讀寫掌握Linux中信號的使用掌握Linux中信號量的使用掌握Linux中共享內(nèi)存的使用掌握Linux中消息隊列的使用 www embedu org 本章的主要內(nèi)容 8 1Linux下進程間通信概述8 2管道8 3信號8 4信號量8 5共享內(nèi)存8 6消息隊列8 7實驗 www embedu org 8 1Linux下進程間通信概述 www embedu org Linux下進程間通信概述 1 Linux下的進程通信手段基本上是從UNIX平臺上的進程通信手段繼承而來的 而對UNIX發(fā)展做出重大貢獻的兩大主力AT T的貝爾實驗室及BSD 加州大學(xué)伯克利分校的伯克利軟件發(fā)布中心 在進程間的通信方面的側(cè)重點有所不同 前者是對UNIX早期的進程間通信手段進行了系統(tǒng)的改進和擴充 形成了 systemVIPC 其通信進程主要局限在單個計算機內(nèi) 后者則跳過了該限制 形成了基于套接口 socket 的進程間通信機制 而Linux則把兩者的優(yōu)勢都繼承了下來 www embedu org Linux下進程間通信概述 2 UNIX進程間通信 IPC 方式包括管道 FIFO以及信號 SystemV進程間通信 IPC 包括SystemV消息隊列 SystemV信號量以及SystemV共享內(nèi)存區(qū) Posix進程間通信 IPC 包括Posix消息隊列 Posix信號量以及Posix共享內(nèi)存區(qū) www embedu org 進程間通信方式的種類 1 1 管道 Pipe 及有名管道 namedpipe 管道可用于具有親緣關(guān)系進程間的通信 有名管道 除具有管道所具有的功能外 它還允許無親緣關(guān)系進程間的通信 2 信號 Signal 信號是在軟件層次上對中斷機制的一種模擬 它是比較復(fù)雜的通信方式 用于通知進程有某事件發(fā)生 一個進程收到一個信號與處理器收到一個中斷請求效果上可以說是一樣的 3 消息隊列 MessgeQueue 消息隊列是消息的鏈接表 包括Posix消息隊列SystemV消息隊列 它克服了前兩種通信方式中信息量有限的缺點 具有寫權(quán)限的進程可以按照一定的規(guī)則向消息隊列中添加新消息 對消息隊列有讀權(quán)限的進程則可以從消息隊列中讀取消息 www embedu org 進程間通信方式的種類 2 4 共享內(nèi)存 Sharedmemory 可以說這是最有用的進程間通信方式 它使得多個進程可以訪問同一塊內(nèi)存空間 不同進程可以及時看到對方進程中對共享內(nèi)存中數(shù)據(jù)的更新 這種通信方式需要依靠某種同步機制 如互斥鎖和信號量等 5 信號量 Semaphore 主要作為進程之間以及同一進程的不同線程之間的同步和互斥手段 6 套接字 Socket 這是一種更為一般的進程間通信機制 它可用于網(wǎng)絡(luò)中不同機器之間的進程間通信 應(yīng)用非常廣泛 www embedu org 8 2管道 www embedu org 管道概述 無名管道是Linux中進程間通信的一種方式 它只能用于具有親緣關(guān)系的進程之間的通信 也就是父子進程或者兄弟進程之間 它是一個半雙工的通信模式 具有固定的讀端和寫端 管道也可以看成是一種特殊的文件 對于它的讀寫也可以使用普通的read 和write 等函數(shù) 但是它不是普通的文件 并不屬于其他任何文件系統(tǒng) 并且只存在于內(nèi)核的內(nèi)存空間中 www embedu org 管道的創(chuàng)建和關(guān)閉 管道是基于文件描述符的通信方式 當(dāng)一個管道建立時 它會創(chuàng)建兩個文件描述符fds 0 和fds 1 其中fds 0 固定用于讀管道 而fd 1 固定用于寫管道 這樣就構(gòu)成了一個半雙工的通道 創(chuàng)建管道可以通過調(diào)用pipe 來實現(xiàn) 管道關(guān)閉時只需使用普通的close 函數(shù)逐個關(guān)閉各個文件描述符 www embedu org 父子進程之間的管道通信 1 用pipe 函數(shù)創(chuàng)建的管道兩端處于一個進程中 由于管道是主要用于在不同進程間通信的 因此這在實際應(yīng)用中沒有太大意義 實際上 通常先是創(chuàng)建一個管道 再通過fork 函數(shù)創(chuàng)建一子進程 該子進程會繼承父進程所創(chuàng)建的管道 www embedu org 父子進程之間的管道通信 2 父子進程分別擁有自己的讀寫通道 為了實現(xiàn)父子進程之間的讀寫 只需把無關(guān)的讀端或?qū)懚说奈募枋龇P(guān)閉即可 此時 父子進程之間就建立起了一條 子進程寫入父進程讀取 的通道 www embedu org 示例 閱讀并運行示例8 2 2 www embedu org 標準流管道 1 與Linux的文件操作中有基于文件流的標準I O操作一樣 管道的操作也支持基于文件流的模式 這種基于文件流的管道主要是用來創(chuàng)建一個連接到另一個進程的管道 這里的 另一個進程 也就是一個可以進行一定操作的可執(zhí)行文件 例如 用戶執(zhí)行 ls l 或者自己編寫的程序 pipe 等 由于這一類操作很常用 因此標準流管道就將一系列的創(chuàng)建過程合并到一個函數(shù)popen 中完成 它所完成的工作有以下幾步 創(chuàng)建一個管道 fork 一個子進程 在父子進程中關(guān)閉不需要的文件描述符 執(zhí)行exec函數(shù)族調(diào)用 執(zhí)行函數(shù)中所指定的命令 www embedu org 標準流管道 2 標準流管道的使用可以大大減少代碼的編寫量 但同時也有一些不利之處 例如 它不如前面管道創(chuàng)建的函數(shù)那樣靈活多樣 并且用popen 創(chuàng)建的管道必須使用標準I O函數(shù)進行操作 但不能使用前面的read write 一類不帶緩沖的I O函數(shù) 與之相對應(yīng) 關(guān)閉用popen 創(chuàng)建的流管道必須使用函數(shù)pclose 來關(guān)閉該管道流 該函數(shù)關(guān)閉標準I O流 并等待命令執(zhí)行結(jié)束 www embedu org 標準流管道 3 www embedu org 示例 閱讀并運行示例8 2 3 www embedu org 有名管道 1 前面介紹的管道是無名管道 它只能用于具有親緣關(guān)系的進程之間 這就大大地限制了管道的使用 有名管道的出現(xiàn)突破了這種限制 它可以使互不相關(guān)的兩個進程實現(xiàn)彼此通信 該管道可以通過路徑名來指出 并且在文件系統(tǒng)中是可見的 在建立了管道之后 兩個進程就可以把它當(dāng)作普通文件一樣進行讀寫操作 使用非常方便 不過值得注意的是 FIFO是嚴格地遵循先進先出規(guī)則的 對管道及FIFO的讀總是從開始處返回數(shù)據(jù) 對它們的寫則把數(shù)據(jù)添加到末尾 它們不支持如lseek 等文件定位操作 有名管道的創(chuàng)建可以使用函數(shù)mkfifo 該函數(shù)類似文件中的open 操作 可以指定管道的路徑和打開的模式 www embedu org 有名管道 2 在創(chuàng)建管道成功之后 就可以使用open read 和write 這些函數(shù)了 與普通文件的開發(fā)設(shè)置一樣 對于為讀而打開的管道可在open 中設(shè)置O RDONLY 對于為寫而打開的管道可在open 中設(shè)置O WRONLY 在這里與普通文件不同的是阻塞問題 www embedu org 有名管道 3 由于普通文件的讀寫時不會出現(xiàn)阻塞問題 而在管道的讀寫中卻有阻塞的可能 這里的非阻塞標志可以在open 函數(shù)中設(shè)定為O NONBLOCK 對于讀進程 若該管道是阻塞打開 且當(dāng)前FIFO內(nèi)沒有數(shù)據(jù) 則對讀進程而言將一直阻塞到有數(shù)據(jù)寫入 若該管道是非阻塞打開 則不論FIFO內(nèi)是否有數(shù)據(jù) 讀進程都會立即執(zhí)行讀操作 即如果FIFO內(nèi)沒有數(shù)據(jù) 則讀函數(shù)將立刻返回0 對于寫進程 若該管道是阻塞打開 則寫操作將一直阻塞到數(shù)據(jù)可以被寫入 若該管道是非阻塞打開而不能寫入全部數(shù)據(jù) 則讀操作進行部分寫入或者調(diào)用失敗 www embedu org 示例 閱讀并運行示例8 2 3 www embedu org 8 3信號 www embedu org 信號概述 1 信號是UNIX中所使用的進程通信的一種最古老的方法 它是在軟件層次上對中斷機制的一種模擬 是一種異步通信方式 信號可以直接進行用戶空間進程和內(nèi)核進程之間的交互 內(nèi)核進程也可以利用它來通知用戶空間進程發(fā)生了哪些系統(tǒng)事件 它可以在任何時候發(fā)給某一進程 而無需知道該進程的狀態(tài) 如果該進程當(dāng)前并未處于執(zhí)行態(tài) 則該信號就由內(nèi)核保存起來 直到該進程恢復(fù)執(zhí)行再傳遞給它為止 如果一個信號被進程設(shè)置為阻塞 則該信號的傳遞被延遲 直到其阻塞被取消時才被傳遞給進程 不可靠信號和可靠信號 www embedu org 信號概述 2 一個不可靠信號的處理過程是這樣的 如果發(fā)現(xiàn)該信號已經(jīng)在進程中注冊 那么就忽略該信號 因此 若前一個信號還未注銷又產(chǎn)生了相同的信號就會產(chǎn)生信號丟失 而當(dāng)可靠信號發(fā)送給一個進程時 不管該信號是否已經(jīng)在進程中注冊 都會被再注冊一次 因此信號就不會丟失 所有可靠信號都支持排隊 而所有不可靠信號都不支持排隊 一個完整的信號生命周期可以分為3個重要階段 這3個階段由4個重要事件來刻畫的 信號產(chǎn)生 信號在進程中注冊 信號在進程中注銷 執(zhí)行信號處理函數(shù) www embedu org 信號概述 3 用戶進程對信號的響應(yīng)可以有3種方式 忽略信號 即對信號不做任何處理 但是有兩個信號不能忽略 即SIGKILL及SIGSTOP 捕捉信號 定義信號處理函數(shù) 當(dāng)信號發(fā)生時 執(zhí)行相應(yīng)的自定義處理函數(shù) 執(zhí)行缺省操作 Linux對每種信號都規(guī)定了默認操作 www embedu org 信號概述 3 www embedu org 信號發(fā)送與捕捉 1 kill 函數(shù)同讀者熟知的kill系統(tǒng)命令一樣 可以發(fā)送信號給進程或進程組 實際上 kill系統(tǒng)命令只是kill 函數(shù)的一個用戶接口 這里需要注意的是 它不僅可以中止進程 實際上發(fā)出SIGKILL信號 也可以向進程發(fā)送其他信號 與kill 函數(shù)所不同的是 raise 函數(shù)允許進程向自身發(fā)送信號 www embedu org 信號發(fā)送與捕捉 2 www embedu org 示例 閱讀并運行示例8 3 2 1 www embedu org 信號發(fā)送與捕捉 3 alarm 也稱為鬧鐘函數(shù) 它可以在進程中設(shè)置一個定時器 當(dāng)定時器指定的時間到時 它就向進程發(fā)送SIGALARM信號 要注意的是 一個進程只能有一個鬧鐘時間 如果在調(diào)用alarm 之前已設(shè)置過鬧鐘時間 則任何以前的鬧鐘時間都被新值所代替 pause 函數(shù)是用于將調(diào)用進程掛起直至捕捉到信號為止 這個函數(shù)很常用 通??梢杂糜谂袛嘈盘柺欠褚训?www embedu org 信號發(fā)送與捕捉 4 閱讀并運行示例8 3 3 2 www embedu org signal 1 信號處理的主要方法有兩種 一種是使用簡單的signal 函數(shù) 另一種是使用信號集函數(shù)組 www embedu org signal 2 structsigaction void sa handler intsigno sigset tsa mask intsa flags void sa restore void sa handler是一個函數(shù)指針 指定信號處理函數(shù) 這里除可以是用戶自定義的處理函數(shù)外 還可以為SIG DFL 采用缺省的處理方式 或SIG IGN 忽略信號 它的處理函數(shù)只有一個參數(shù) 即信號值 sa mask是一個信號集 它可以指定在信號處理程序執(zhí)行過程中哪些信號應(yīng)當(dāng)被屏蔽 在調(diào)用信號捕獲函數(shù)之前 該信號集要加入到信號的信號屏蔽字中 sa flags中包含了許多標志位 是對信號進行處理的各個選擇項 www embedu org 示例 閱讀并運行示例8 3 3 1 www embedu org 信號集函數(shù)組 1 使用信號集函數(shù)組處理信號時涉及一系列的函數(shù) 這些函數(shù)按照調(diào)用的先后次序可分為以下幾大功能模塊 創(chuàng)建信號集合 注冊信號處理函數(shù)以及檢測信號 其中 創(chuàng)建信號集合主要用于處理用戶感興趣的一些信號 其函數(shù)包括以下幾個 sigemptyset 將信號集合初始化為空 sigfillset 將信號集合初始化為包含所有已定義的信號的集合 sigaddset 將指定信號加入到信號集合中去 sigdelset 將指定信號從信號集合中刪去 sigismember 查詢指定信號是否在信號集合之中 www embedu org 信號集函數(shù)組 2 注冊信號處理函數(shù)主要用于決定進程如何處理信號 這里要注意的是 信號集里的信號并不是真正可以處理的信號 只有當(dāng)信號的狀態(tài)處于非阻塞狀態(tài)時才會真正起作用 因此 首先使用sigprocmask 函數(shù)檢測并更改信號屏蔽字 信號屏蔽字是用來指定當(dāng)前被阻塞的一組信號 它們不會被進程接收 然后使用sigaction 函數(shù)來定義進程接收到特定信號之后的行為 檢測信號是信號處理的后續(xù)步驟 因為被阻塞的信號不會傳遞給進程 所以這些信號就處于 未處理 狀態(tài) 也就是進程不清楚它的存在 sigpending 函數(shù)允許進程檢測 未處理 信號 并進一步?jīng)Q定對它們作何處理 www embedu org 信號集函數(shù)組 3 www embedu org 信號集函數(shù)組 4 www embedu org 示例 閱讀并運行示例8 3 3 2 www embedu org 8 4信號量 www embedu org 信號量概述 1 在多任務(wù)操作系統(tǒng)環(huán)境下 多個進程會同時運行 并且一些進程之間可能存在一定的關(guān)聯(lián) 多個進程可能為了完成同一個任務(wù)會相互協(xié)作 這樣形成進程之間的同步關(guān)系 而且在不同進程之間 為了爭奪有限的系統(tǒng)資源 硬件或軟件資源 會進入競爭狀態(tài) 這就是進程之間的互斥關(guān)系 進程之間的互斥與同步關(guān)系存在的根源在于臨界資源 臨界資源是在同一個時刻只允許有限個 通常只有一個 進程可以訪問 讀 或修改 寫 的資源 通常包括硬件資源 處理器 內(nèi)存 存儲器以及其他外圍設(shè)備等 和軟件資源 共享代碼段 共享結(jié)構(gòu)和變量等 訪問臨界資源的代碼叫做臨界區(qū) 臨界區(qū)本身也會成為臨界資源 www embedu org 信號量概述 2 信號量是用來解決進程之間的同步與互斥問題的一種進程之間通信機制 包括一個稱為信號量的變量和在該信號量下等待資源的進程等待隊列 以及對信號量進行的兩個原子操作 PV操作 其中信號量對應(yīng)于某一種資源 取一個非負的整型值 信號量值指的是當(dāng)前可用的該資源的數(shù)量 若它等于0則意味著目前沒有可用的資源 PV原子操作的具體定義為 P操作 如果有可用的資源 信號量值 0 則占用一個資源 給信號量值減去一 進入臨界區(qū)代碼 如果沒有可用的資源 信號量值等于0 則被阻塞到 直到系統(tǒng)將資源分配給該進程 進入等待隊列 一直等到資源輪到該進程 V操作 如果在該信號量的等待隊列中有進程在等待資源 則喚醒一個阻塞進程 如果沒有進程等待它 則釋放一個資源 給信號量值加一 www embedu org 信號量概述 3 使用信號量訪問臨界區(qū)的偽代碼所下所示 設(shè)R為某種資源 S為資源R的信號量 INIT VAL S 對信號量S進行初始化 非臨界區(qū) P S 進行P操作 臨界區(qū) 使用資源R 只有有限個 通常只有一個 進程被允許進入該區(qū) V S 進行V操作 非臨界區(qū) www embedu org 信號量的使用 1 第一步 創(chuàng)建信號量或獲得在系統(tǒng)已存在的信號量 此時需要調(diào)用semget 函數(shù) 不同進程通過使用同一個信號量鍵值來獲得同一個信號量 第二步 初始化信號量 此時使用semctl 函數(shù)的SETVAL操作 當(dāng)使用二維信號量時 通常將信號量初始化為1 第三步 進行信號量的PV操作 此時調(diào)用semop 函數(shù) 這一步是實現(xiàn)進程之間的同步和互斥的核心工作部分 第四步 如果不需要信號量 則從系統(tǒng)中刪除它 此時使用semclt 函數(shù)的IPC RMID操作 此時需要注意 在程序中不應(yīng)該出現(xiàn)對已經(jīng)被刪除的信號量的操作 www embedu org 信號量的使用 2 www embedu org 信號量的使用 3 www embedu org 信號量的使用 4 www embedu org 示例 閱讀并運行示例8 4 www embedu org 8 5共享內(nèi)存 www embedu org 共享內(nèi)存概述 共享內(nèi)存是一種最為高效的進程間通信方式 因為進程可以直接讀寫內(nèi)存 不需要任何數(shù)據(jù)的拷貝 為了在多個進程間交換信息 內(nèi)核專門留出了一塊內(nèi)存區(qū) 這段內(nèi)存區(qū)可以由需要訪問的進程將其映射到自己的私有地址空間 因此 進程就可以直接讀寫這一內(nèi)存區(qū)而不需要進行數(shù)據(jù)的拷貝 從而大大提高了效率 當(dāng)然 由于多個進程共享一段內(nèi)存 因此也需要依靠某種同步機制 如互斥鎖和信號量等 www embedu org 共享內(nèi)存的應(yīng)用 1 共享內(nèi)存的實現(xiàn)分為兩個步驟 第一步是創(chuàng)建共享內(nèi)存 這里用到的函數(shù)是shmget 也就是從內(nèi)存中獲得一段共享內(nèi)存區(qū)域 第二步映射共享內(nèi)存 也就是把這段創(chuàng)建的共享內(nèi)存映射到具體的進程空間中 這里使用的函數(shù)是shmat 到這里 就可以使用這段共享內(nèi)存了 也就是可以使用不帶緩沖的I O讀寫命令對其進行操作 除此之外 當(dāng)然還有撤銷映射的操作 其函數(shù)為shmdt www embedu org 共享內(nèi)存的應(yīng)用 2 www embedu org 共享內(nèi)存的應(yīng)用 3 www embedu org 示例 閱讀并運行示例8 5 2 www embedu org 8 6消息隊列 www embedu org 消息隊列 1 消息隊列就是一些消息的列表 用戶可以從消息隊列中添加消息和讀取消息等 從這點上看 消息隊列具有一定的FIFO特性 但是它可以實現(xiàn)消息的隨機查詢 比FIFO具有更大的優(yōu)勢 同時 這些消息又是存在于內(nèi)核中的 由 隊列

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論