新聞中心
在 Linux 系統(tǒng)中,進程間通信(IPC)是非常重要的一部分。進程間通信指的是不同進程之間進行數(shù)據(jù)交換的過程。進程間傳遞數(shù)據(jù)技巧是一種重要的進程通信方法,通過它可以實現(xiàn)進程之間的數(shù)據(jù)傳遞,使進程之間的數(shù)據(jù)交換更加高效、安全和可靠。下面,我們就來介紹一下如何。

一、Linux 下的進程間傳遞數(shù)據(jù)技巧簡介
Linux 下的進程間傳遞數(shù)據(jù)技巧主要包括管道、消息隊列、共享內(nèi)存和信號等。它們都是使用進程間通信技術(shù)實現(xiàn)的,但是具體實現(xiàn)方式有所不同。下面,我們來逐一介紹這幾種技巧。
1. 管道
管道是一種單向通信方式,其本質(zhì)上是一個緩沖區(qū),可以用來實現(xiàn)進程之間的數(shù)據(jù)傳輸。管道分為匿名管道和命名管道兩種方式。
(1)匿名管道:只存在于創(chuàng)建它的進程和它創(chuàng)建的子進程之間,可以用于進程間的簡單通信。
(2)命名管道:存在于文件系統(tǒng)中,可以被多個進程以只讀或只寫的方式打開,用于進程間的復(fù)雜通信。
2. 消息隊列
消息隊列是一種常用的進程間通信機制,其目的是允許不同進程之間交換數(shù)據(jù),克服了管道只能傳輸無格式字節(jié)流數(shù)據(jù)的限制。使用消息隊列傳輸消息時,其內(nèi)部是通過一個緩沖隊列來實現(xiàn)的,支持多個進程之間的消息傳輸。
3. 共享內(nèi)存
共享內(nèi)存是一種高速的進程間通信方式。使用共享內(nèi)存?zhèn)鬏敂?shù)據(jù)時,其內(nèi)部是通過將同一個物理內(nèi)存映射到多個進程的虛擬地址空間中來實現(xiàn)的,多個進程可以共享這個內(nèi)存區(qū)域,以實現(xiàn)實時數(shù)據(jù)傳輸。
4. 信號
信號是 Linux 下的一種基本進程間通信機制。它是 Linux 內(nèi)核和應(yīng)用程序之間進行通信的主要方式之一,通過向進程發(fā)送信號來通知它們發(fā)生了某些特定的事件。常見的信號包括進程終止信號、中斷信號和定時器信號等。
二、Linux 下進程間傳遞數(shù)據(jù)技巧的應(yīng)用場景
Linux 下的進程間傳遞數(shù)據(jù)技巧可以應(yīng)用于多種場景,如網(wǎng)絡(luò)通信、多線程編程以及分布式系統(tǒng)等方面。下面我們來逐一介紹這些場景。
1. 網(wǎng)絡(luò)通信
在網(wǎng)絡(luò)通信中,進程間通信技術(shù)是必不可少的。使用進程間通信技術(shù)可以實現(xiàn)進程之間的數(shù)據(jù)傳遞,使得進程之間的數(shù)據(jù)交換更加高效、安全和可靠。常見的應(yīng)用場景包括服務(wù)器端程序、客戶端程序以及網(wǎng)絡(luò)協(xié)議棧等。
2. 多線程編程
在多線程編程中,多個線程之間需要進行數(shù)據(jù)共享和協(xié)調(diào)。使用進程間通信技術(shù)可以實現(xiàn)多個線程之間的數(shù)據(jù)交換和消息傳遞,以實現(xiàn)線程之間的協(xié)作和數(shù)據(jù)同步。常見的應(yīng)用場景包括多線程數(shù)據(jù)處理、線程池管理以及多線程任務(wù)隊列等。
3. 分布式系統(tǒng)
在分布式系統(tǒng)中,進程間通信技術(shù)是構(gòu)建分布式系統(tǒng)的核心技術(shù)之一。使用進程間通信技術(shù)可以實現(xiàn)不同計算機節(jié)點之間的數(shù)據(jù)共享和消息傳遞,以實現(xiàn)分布式數(shù)據(jù)處理和協(xié)調(diào)。常見的應(yīng)用場景包括分布式計算、分布式數(shù)據(jù)庫以及分布式存儲等。
三、Linux 下進程間傳遞數(shù)據(jù)技巧的實現(xiàn)
在 Linux 系統(tǒng)中,實現(xiàn)進程間傳遞數(shù)據(jù)技巧需要使用到相應(yīng)的系統(tǒng)調(diào)用和庫函數(shù)。以下是常見的幾種實現(xiàn)方法。
1. 管道
在 Linux 系統(tǒng)中,可以使用 pipe 系統(tǒng)調(diào)用創(chuàng)建匿名管道,并使用 read 和 write 系統(tǒng)調(diào)用在兩個進程之間傳遞數(shù)據(jù)。命名管道可以通過 mkfifo 系統(tǒng)調(diào)用創(chuàng)建,進程可以通過文件 I/O 函數(shù)來進行讀寫操作。
2. 消息隊列
在 Linux 系統(tǒng)中,可以使用 msgget 系統(tǒng)調(diào)用來創(chuàng)建消息隊列,并使用 msgsnd 和 msgrcv 系統(tǒng)調(diào)用在進程之間傳遞消息。msgget 系統(tǒng)調(diào)用用于創(chuàng)建或訪問一個已經(jīng)存在的消息隊列,msgsnd 系統(tǒng)調(diào)用用于向消息隊列發(fā)送消息,msgrcv 系統(tǒng)調(diào)用用于從消息隊列中接收消息。
3. 共享內(nèi)存
在 Linux 系統(tǒng)中,可以使用 shmget 系統(tǒng)調(diào)用創(chuàng)建共享內(nèi)存區(qū)域,并使用 shmat 和 shmdt 系統(tǒng)調(diào)用將共享內(nèi)存區(qū)域映射到進程的虛擬地址空間中。shmget 系統(tǒng)調(diào)用用于創(chuàng)建或訪問一個共享內(nèi)存區(qū)域,shmat 系統(tǒng)調(diào)用用于將共享內(nèi)存區(qū)域映射到進程的虛擬地址空間中,shmdt 系統(tǒng)調(diào)用用于取消共享內(nèi)存區(qū)域的映射。
4. 信號
在 Linux 系統(tǒng)中,可以使用 kill 系統(tǒng)調(diào)用向指定的進程發(fā)送信號。kill 系統(tǒng)調(diào)用可以向指定的進程發(fā)送任意用戶定義的信號,例如進程終止信號、中斷信號和定時器信號等。進程可以通過信號處理函數(shù)來響應(yīng)接收到的信號。
四、
是一種非常重要的通信技術(shù),可以用于各種應(yīng)用場景,如網(wǎng)絡(luò)通信、多線程編程以及分布式系統(tǒng)等。在 Linux 系統(tǒng)中,管道、消息隊列、共享內(nèi)存和信號都是常用的進程通信機制。通過合理的選用和使用這些技巧,可以實現(xiàn)進程間的高效、安全和可靠的數(shù)據(jù)傳遞。因此,對于 Linux 系統(tǒng)開發(fā)人員來說,熟練使用進程間傳遞數(shù)據(jù)技巧是必備的技能之一。
相關(guān)問題拓展閱讀:
- 在linux編程中若一個用戶程序希望將一組數(shù)據(jù)傳遞給kernel有幾種方式
- 架構(gòu)師進階:Linux進程間如何共享內(nèi)存
在linux編程中若一個用戶程序希望將一組數(shù)據(jù)傳遞給kernel有幾種方式
教科書里的Linux代碼例子都已作古,所以看到的代碼不能當真,領(lǐng)會意思就行了
比如以前的init進程的啟動代碼
execve(init_filename,argv_init,envp_init);
現(xiàn)在改為
static void run_init_process(char *init_filename)
{
argv_init = init_filename;
kernel_execve(init_filename, argv_init, envp_init);
}
好的,聰明人就發(fā)現(xiàn),linux內(nèi)核中調(diào)用用戶空間的程序可以使用init這樣的方式,調(diào)用 kernel_execve
不過內(nèi)核還是提供了更好的輔助接口call_usermodehelper,自然最后也是調(diào)用kernel_execve
調(diào)用特定的內(nèi)核函數(shù)(系統(tǒng)調(diào)用)是 GNU/Linux 中軟件開發(fā)的原本就有的組成部分。但如果方向反過來呢,內(nèi)核空間調(diào)用用戶空間?確實有一些有這種特性的應(yīng)用程序需要每天使用。例如,當內(nèi)核找到一個設(shè)備, 這時需要加載某個模塊,進程如何處理?動態(tài)模塊加載在內(nèi)核通過 usermode-helper 進程進行。
讓我們從探索 usermode-helper 應(yīng)用程序編程接口(API)以及在內(nèi)核中使用的例子開始。 然后,使用 API 構(gòu)造一個示例應(yīng)用程序,以便更好地理解其工作原理與局限。
usermode-helper API
usermode-helper API 是個很簡單的 API,其選項為用戶熟知。例如,要創(chuàng)建一個用戶空間進程,通常只要設(shè)置名稱為 executable,選項都為 executable,以及一組環(huán)境變量(指向 execve 主頁)念橋。創(chuàng)建內(nèi)核進程也是一樣。但由于創(chuàng)建內(nèi)核空間進程,還需要設(shè)置一些額外選項。
內(nèi)核版本
本文探討的是 2.6.27 版內(nèi)核的 usermode-helper API。
表 1 展示的是 usermode-helper API 中一組關(guān)鍵的內(nèi)核函數(shù)
表 1. usermode-helper API 中的核心函數(shù)
API 函數(shù)
描述
call_usermodehelper_setup 準備 user-land 調(diào)用的處理函數(shù)
call_usermodehelper_setkeys 設(shè)置 helper 的會話密鑰
call_usermodehelper_setcleanup 為 helper 設(shè)置一個清空函數(shù)
call_usermodehelper_stdinpipe 為 helper 創(chuàng)建 stdin 管道
call_usermodehelper_exec 調(diào)用 user-land
表 2 中還有一些簡化函仔嫌猛數(shù),它們封裝了的幾個內(nèi)者斗核函數(shù)(用一個調(diào)用代替多個調(diào)用)。這些簡化函數(shù)在很多情況下都很有用,因此盡可能使用他們。
表 2. usermode-helper API 的簡化
API 函數(shù)
描述
call_usermodehelper 調(diào)用 user-land
call_usermodehelper_pipe 使用 stdin 管道調(diào)用 user-land
call_usermodehelper_keys 使用會話密鑰調(diào)用 user-land
讓我們先瀏覽一遍這些核心函數(shù),然后探索簡化函數(shù)提供了哪些功能。核心 API 使用了一個稱為subprocess_info 結(jié)構(gòu)的處理函數(shù)引用進行操作。該結(jié)構(gòu)(可在 ./kernel/kmod.c 中找到)了給定的 usermode-helper 實例的所有必需元素。該結(jié)構(gòu)引用從 call_usermodehelper_setup 調(diào)用返回。該結(jié)構(gòu)(以及后續(xù)調(diào)用)將會在 call_usermodehelper_setkeys(用于存儲憑證)、call_usermodehelper_setcleanup 以及 call_usermodehelper_stdinpipe 的調(diào)用中進一步配置。最后,一旦配置完成,就可通過調(diào)用 call_usermodehelper_exec 來調(diào)用配置好的用戶模式應(yīng)用程序。
聲明
該方法提供了一個從內(nèi)核調(diào)用用戶空間應(yīng)用程序必需的函數(shù)。盡管這項功能有合理用途,還應(yīng)仔細考慮是否需要其他實現(xiàn)。這是一個方法,但其他方法會更合適。
核心函數(shù)提供了更大程度的控制,其中 helper 函數(shù)在單個調(diào)用中完成了大部分工作。管道相關(guān)調(diào)用(call_usermodehelper_stdinpipe 和 helper 函數(shù) call_usermodehelper_pipe)創(chuàng)建了一個相聯(lián)管道供 helper 使用。具體地說,創(chuàng)建了管道(內(nèi)核中的文件結(jié)構(gòu))。用戶空間應(yīng)用程序?qū)艿揽勺x,內(nèi)核對管道可寫。對于本文,核心轉(zhuǎn)儲只是使用 usermode-helper 管道的應(yīng)用程序。在該應(yīng)用程序(./fs/exec.c do_coredump())中,核心轉(zhuǎn)儲通過管道從內(nèi)核空間寫到用戶空間。
這些函數(shù)與 sub_processinfo 以及 subprocess_info 結(jié)構(gòu)的細節(jié)之間的關(guān)系如圖 1 所示。
圖 1. Usermode-helper API 關(guān)系
表 2 中的簡化函數(shù)內(nèi)部執(zhí)行 call_usermodehelper_setup 函數(shù)和 call_usermodehelper_exec 函數(shù)。表 2 中最后兩個調(diào)用分別調(diào)用的是 call_usermodehelper_setkeys 和 call_usermodehelper_stdinpipe??梢栽?./kernel/kmod.c 找到 call_usermodehelper_pipe 和 call_usermodehelper 的代碼,在 ./include/linux/kmod.h 中找到 call_usermodhelper_keys 的代碼。
為什么要從內(nèi)核調(diào)用用戶空間應(yīng)用程序?
現(xiàn)在讓我們看一看 usermode-helper API 所使用的內(nèi)核空間。表 3 提供的并不是專門的應(yīng)用程序列表,而是一些有趣應(yīng)用的示例。
表 3. 內(nèi)核中的 usermode-helper API 應(yīng)用程序
應(yīng)用程序
源文件位置
內(nèi)核模塊調(diào)用 ./kernel/kmod.c
電源管理 ./kernel/sys.c
控制組 ./kernel/cgroup.c
安全密匙生成 ./security/keys/request_key.c
內(nèi)核事件交付 ./lib/kobject_uevent.c
最直接的 usermode-helper API 應(yīng)用程序是從內(nèi)核空間加載內(nèi)核模塊。request_module 函數(shù)封裝了 usermode-helper API 的功能并提供了簡單的接口。在一個常用的模塊中,內(nèi)核指定一個設(shè)備或所需服務(wù)并調(diào)用 request_module 來加載模塊。通過使用 usermode-helper API,模塊通過 modprobe 加載到內(nèi)核(應(yīng)用程序通過 request_module 在用戶空間被調(diào)用)。
與模塊加載類似的應(yīng)用程序是設(shè)備熱插拔(在運行時添加或刪除設(shè)備)。該特性是通過使用 usermode-helper API,調(diào)用用戶空間的 /in/hotplug 工具實現(xiàn)的。
關(guān)于 usermode-helper API 的一個有趣的應(yīng)用程序(通過 request_module) 是文本搜索 API(./lib/textsearch.c)。該應(yīng)用程序在內(nèi)核中提供了一個可配置的文本搜索基礎(chǔ)架構(gòu)。該應(yīng)用程序使用 usermode-helper API 將搜索算法當作可加載模塊進行動態(tài)加載。在 2.6.30 內(nèi)核版本中,支持三個算法,包括 Boyer-Moore(./lib/ts_bm.c),簡單固定狀態(tài)機方法(./lib/ts_f.c),以及 Knuth-Morris-Pratt 算法(./lib/ts_kmp.c)。
usermode-helper API 還支持 Linux 按照順序關(guān)閉系統(tǒng)。當需要系統(tǒng)關(guān)閉電源時,內(nèi)核調(diào)用用戶空間的 /in/poweroff 命令來完成。其他應(yīng)用程序如 表 3 所示,表中附有其源文件位置。
Usermode-helper API 內(nèi)部
在 kernel/kmod.c 中可以找到 usermode-helper API 的源代碼 和 API(展示了主要的用作內(nèi)核空間的內(nèi)核模塊加載器)。這個實現(xiàn)使用 kernel_execve 完成臟工作(dirty work)。請注意 kernel_execve是在啟動時開啟 init 進程的函數(shù),而且未使用 usermode-helper API。
usermode-helper API 的實現(xiàn)相當簡單直觀(見圖 2)。usermode-helper 從調(diào)用call_usermodehelper_exec 開始執(zhí)行(它用于從預(yù)先配置好的 subprocess_info 結(jié)構(gòu)中清除用戶空間應(yīng)用程序)。該函數(shù)接受兩個參數(shù):subprocess_info 結(jié)構(gòu)引用和一個枚舉類型(不等待、等待進程中止及等待進程完全結(jié)束)。subprocess_info(或者是,該結(jié)構(gòu)的 work_struct 元素)然后被壓入工作隊列(khelper_wq),然后隊列異步執(zhí)行調(diào)用。
圖 2. usermode-helper API 內(nèi)部實現(xiàn)
當一個元素放入 khelper_wq 時,工作隊列的處理函數(shù)就被調(diào)用(本例中是__call_usermodehelper),它在 khelper 線程中運行。該函數(shù)從將 subprocess_info 結(jié)構(gòu)出隊開始,此結(jié)構(gòu)包含所有用戶空間調(diào)用所需信息。該路徑下一步取決于 wait 枚舉變量。如果請求者想要等整個進程結(jié)束,包含用戶空間調(diào)用(UMH_WAIT_PROC)或者是根本不等待(UMH_NO_WAIT),那么會從 wait_for_helper 函數(shù)創(chuàng)建一個內(nèi)核線程。否則,請求者只是等待用戶空間應(yīng)用程序被調(diào)用(UMH_WAIT_EXEC),但并不完全。這種情況下,會為____call_usermodehelper() 創(chuàng)建一個內(nèi)核線程。
在 wait_for_helper 線程中,會安裝一個 SIGCHLD 信號處理函數(shù),并為 ____call_usermodehelper 創(chuàng)建另一個內(nèi)核線程。但在 wait_for_helper 線程中,會調(diào)用 sys_wait4 來等待____call_usermodehelper 內(nèi)核線程(由 SIGCHLD 信號指示)結(jié)束。然后線程執(zhí)行必要的清除工作(為UMH_NO_WAIT 釋放結(jié)構(gòu)空間或簡單地向 call_usermodehelper_exec() 回送一個完成報告)。
函數(shù) ____call_usermodehelper 是實際讓應(yīng)用程序在用戶空間啟動的地方。該函數(shù)首先解鎖所有信號并設(shè)置會話密鑰環(huán)。它還安裝了 stdin 管道(如果有請求)。進行了一些安裝以后,用戶空間應(yīng)用程序通過 kernel_execve(來自 kernel/syscall.c)被調(diào)用,此文件包含此前定義的 path、argv 清單(包含用戶空間應(yīng)用程序名稱)以及環(huán)境。當該進程完成后,此線程通過調(diào)用 do_exit() 而產(chǎn)生。
該進程還使用了 Linux 的 completion,它是像信號一樣的操作。當 call_usermodehelper_exec 函數(shù)被調(diào)用后,就會聲明 completion。當 subprocess_info 結(jié)構(gòu)放入 khelper_wq 后,會調(diào)用wait_for_completion(使用 completion 變量作為參數(shù))。請注意此變量會存儲到 subprocess_info 結(jié)構(gòu)作為 complete 字段。當子線程想要喚醒 call_usermodehelper_exec 函數(shù),會調(diào)用內(nèi)核方法complete,并判斷來自 subprocess_info 結(jié)構(gòu)的 completion 變量。該調(diào)用會解鎖此函數(shù)使其能繼續(xù)??梢栽?include/linux/completion.h 中找到 API 的實現(xiàn)。
應(yīng)用程序示例
現(xiàn)在,讓我們看看 usermode-helper API 的簡單應(yīng)用。首先看一下標準 API,然后學(xué)習(xí)如何使用 helper 函數(shù)使事情更簡單。
在該例中,首先開發(fā)了一個簡單的調(diào)用 API 的可加載內(nèi)核模塊。清單 1 展示了樣板模塊功能,定義了模塊入口和出口函數(shù)。這兩個函數(shù)根據(jù)模塊的 modprobe(模塊入口函數(shù))或 inod(模塊入口函數(shù)),以及 rmmod(模塊出口函數(shù))被調(diào)用。
清單 1. 模塊樣板函數(shù)
#include
#include
#include
MODULE_LICENSE( “GPL” );
static int __init mod_entry_func( void )
{
return umh_test();
}
static void __exit mod_exit_func( void )
{
return;
}
module_init( mod_entry_func );
module_exit( mod_exit_func );
usermode-helper API 的使用如 清單 2 所示,其中有詳細描述。函數(shù)開始是聲明所需變量和結(jié)構(gòu)。以subprocess_info 結(jié)構(gòu)開始,它包含所有的執(zhí)行用戶空間調(diào)用的信息。該調(diào)用在調(diào)用call_usermodehelper_setup 時初始化。下一步,定義參數(shù)列表,使 argv 被調(diào)用。該列表與普通 C 程序中的 argv 列表類似,定義了應(yīng)用程序(數(shù)組之一個元素)和參數(shù)列表。需要 NULL 終止符來提示列表末尾。請注意這里的 argc 變量(參數(shù)數(shù)量)是隱式的,因為 argv 列表的長度已經(jīng)知道。該例中,應(yīng)用程序名是 /usr/bin/logger,參數(shù)是 help!,然后是 NULL 終止符。下一個所需變量是環(huán)境數(shù)組(envp)。該數(shù)組是一組定義用戶空間應(yīng)用程序執(zhí)行環(huán)境的參數(shù)列表。本例中,定義一些常用的參數(shù),這些參數(shù)用于定義 shell 并以 NULL 條目結(jié)束。
清單 2. 簡單的 usermode_helper API 測試
static int umh_test( void )
{
struct subprocess_info *sub_info;
char *argv = { “/usr/bin/logger”, “help!”, NULL };
static char *envp = {
“HOME=/”,
“TERM=linux”,
“PATH=/in:/bin:/usr/in:/usr/bin”, NULL };
sub_info = call_usermodehelper_setup( argv, argv, envp, GFP_ATOMIC );
if (sub_info == NULL) return -ENOMEM;
return call_usermodehelper_exec( sub_info, UMH_WAIT_PROC );
}
下一步,調(diào)用 call_usermodehelper_setup 來創(chuàng)建已初始化的 subprocess_info 結(jié)構(gòu)。請注意使用了先前初始化的變量以及指示用于內(nèi)存初始化的 GFP 屏蔽第四個參數(shù)。在安裝函數(shù)內(nèi)部,調(diào)用了kzalloc(分配內(nèi)核內(nèi)存并清零)。該函數(shù)需要 GFP_ATOMIC 或 GFP_KERNEL 標志(前者定義調(diào)用不可以休眠,后者定義可以休眠)??焖贉y試新結(jié)構(gòu)(即,非 NULL)后,使用 call_usermodehelper_exec 函數(shù)繼續(xù)調(diào)用。該函數(shù)使用 subprocess_info 結(jié)構(gòu)以及定義是否等待的枚舉變量(在 “Usermode-helper API 內(nèi)部” 一節(jié)中有描述)。全部完成! 模塊一旦加載,就可以在 /var/log/messages 文件中看到信息。
還可以通過 call_usermodehelper API 函數(shù)進一步簡化進程,它同時執(zhí)行 call_usermodehelper_setup和 call_usermodehelper_exec 函數(shù)。如清單 3 所示,它不僅刪除函數(shù),還消除了調(diào)用者管理subprocess_info 結(jié)構(gòu)的必要性。
清單 3. 更簡單的 usermode-helper API 測試
static int umh_test( void )
{
char *argv = { “/usr/bin/logger”, “help!”, NULL };
static char *envp = {
“HOME=/”,
“TERM=linux”,
“PATH=/in:/bin:/usr/in:/usr/bin”, NULL };
return call_usermodehelper( argv, argv, envp, UMH_WAIT_PROC );
}
架構(gòu)師進階:Linux進程間如何共享內(nèi)存
共享內(nèi)存 IPC 原理
共享內(nèi)存進程間通信機制主要用于實現(xiàn)進程間大量的數(shù)據(jù)傳輸,下圖所示為進程間使用芹汪共享內(nèi)存實現(xiàn)大量數(shù)據(jù)傳輸?shù)氖疽鈭D:
640
共享內(nèi)存是在內(nèi)存中單獨開辟的一段內(nèi)存空間,這段內(nèi)存空間有自己特有的數(shù)據(jù)結(jié)構(gòu),包括訪問權(quán)限、大小和最近訪問的時間等。該數(shù)據(jù)結(jié)構(gòu)定義如下:
from /usr/include/linux/shm.h
struct shmid_ds {
struct ipc_perm shm_perm; /* operation perms 操作權(quán)限 */
int shm_segsz; /* size of segment (bytes) 段長度大小 */
__kernel_time_t shm_atime; /* last attach time 最近attach時間 */
__kernel_time_t shm_dtime; /* last detach time 最近detach時間 */
__kernel_time_t shm_ctime; /* last change time 最近change時間 */
__kernel_ipc_pid_t shm_cpid; /* pid of creator 創(chuàng)建者pid */
__kernel_ipc_pid_t shm_lpid; /* pid of last operator 最近操作pid */
unsigned short shm_nattch; /* no. of current attaches */
unsigned short shm_unused; /* compatibility */
void *shm_unused2; /* ditto – used by DIPC */
void *shm_unused3; /* unused */|
};
兩個進程在使用此共享內(nèi)存空間之前,需要在進程地址空間與共享內(nèi)存空間之間建立聯(lián)系,即將共享內(nèi)存空間掛載到進程中。
系統(tǒng)對共享內(nèi)存做了以下限制:
#define SHMMAX 0x/* max shared seg size (bytes) 更大共享段大小 */
#define SHMMIN 1 /* min shared seg size (bytes) 最小共享段大小 */
#define SHMMNI 4096 /* max num of segs system wide */
#define SHMALL (SHMMAX/getpagesize()*(SHMMNI/16))|
define SHMSEG SHMMNI /* max shared segs per process */
Linux 共享內(nèi)存管理
1.創(chuàng)建共享內(nèi)存
#include #include
/*
* 之一個參數(shù)為 key 值,一般由 ftok() 函數(shù)產(chǎn)生
* 第二個參數(shù)為欲創(chuàng)建的共享內(nèi)存段大小(單位為字節(jié))
* 第三個參數(shù)用來標識共享內(nèi)存段的創(chuàng)建標識
*/
int shmget(key_t key, size_t size, int shm);
2.共享內(nèi)存控制
#include #include
/*
* 之一個參數(shù)為要操作的共享內(nèi)存標識符
* 第二個參數(shù)為要執(zhí)行的操作
* 第三個參數(shù)為 shmid_ds 結(jié)構(gòu)的臨時共享內(nèi)存變量信息
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
3.映射共享內(nèi)存對象
系統(tǒng)調(diào)用 shmat() 函數(shù)實現(xiàn)將一個共享內(nèi)存段映射到調(diào)悶宴用進程的數(shù)據(jù)段中,并返回內(nèi)存空間首地址,其函數(shù)聲明如下:
#include
#include
/*
* 之一個參數(shù)為要操作的共享內(nèi)存標識符
* 第二個參數(shù)用來指定共享內(nèi)存的映射地址,非0則為此參數(shù),為0的話由系統(tǒng)分配
* 第三個參數(shù)用來指定共享內(nèi)存段的訪問權(quán)限和映射條件
*/
void *shmat(int shmid, const void *shmaddr, int shm);
4.分離共享內(nèi)存對象
在使用完畢共享內(nèi)存空間后,需要使用 shmdt() 函數(shù)調(diào)用將其與當前進程分離。函數(shù)聲明如下:嫌罩仔
#include
#include
/*
* 參數(shù)為分配的共享內(nèi)存首地址
*/
int shmdt(const void *shmaddr);
共享內(nèi)存在父子進程間遵循的約定
1.使用 fork() 函數(shù)創(chuàng)建一個子進程后,該進程繼承父親進程掛載的共享內(nèi)存。
2.如果調(diào)用 exec() 執(zhí)行一個新的程序,則所有掛載的共享內(nèi)存將被自動卸載。
3.如果在某個進程中調(diào)用了 exit() 函數(shù),所有掛載的共享內(nèi)存將與當前進程脫離關(guān)系。
程序?qū)嵗?/p>
申請一段共享內(nèi)存,父進程在首地址處存入一整數(shù),子進程讀出。
#include
#include
#include
#include
#include
#include
#define SHM_SIZE 1024
int main()
{
int shm_id, pid;
int *ptr = NULL;
/* 申請共享內(nèi)存 */
shm_id = shmget((key_t)1004, SHM_SIZE, IPC_CREAT | 0600);
/* 映射共享內(nèi)存到進程地址空間 */
ptr = (int*)shmat(shm_id, 0, 0);
printf(“Attach addr is %p “, ptr);
*ptr = 1004;
printf(“The Value of Parent is : %d “, *ptr);
if((pid=fork()) == -1){
perror(“fork Err”);
exit(0);
}
else if(!pid){
printf(“The Value of Child is : %d “, *ptr);
exit(0);
}else{
sleep(1);
/* 解除映射 */
shmdt(ptr);
/* 刪除共享內(nèi)存 */
shmctl(shm_id, IPC_RMID, 0);
}
return 0;
}
輸出結(jié)果:
640
linux 給進程傳遞數(shù)據(jù)的介紹就聊到這里吧,感謝你花時間閱讀本站內(nèi)容,更多關(guān)于linux 給進程傳遞數(shù)據(jù),運用 Linux 實現(xiàn)進程間傳遞數(shù)據(jù)技巧,在linux編程中若一個用戶程序希望將一組數(shù)據(jù)傳遞給kernel有幾種方式,架構(gòu)師進階:Linux進程間如何共享內(nèi)存的信息別忘了在本站進行查找喔。
香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗。專業(yè)提供云主機、虛擬主機、域名注冊、VPS主機、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。
當前標題:運用Linux實現(xiàn)進程間傳遞數(shù)據(jù)技巧(linux給進程傳遞數(shù)據(jù))
轉(zhuǎn)載注明:http://m.fisionsoft.com.cn/article/cdidghe.html


咨詢
建站咨詢
