當前位置:編程學習大全網 - 編程語言 - Linux下使用能否使用C***享內存存放指針

Linux下使用能否使用C***享內存存放指針

***享內存指在多處理器的計算機系統中,可以被不同中央處理器(CPU)訪問的大容量內存。由於多個CPU需要快速訪問存儲器,這樣就要對存儲器進行緩存(Cache)。任何壹個緩存的數據被更新後,由於其他處理器也可能要存取,***享內存就需要立即更新,否則不同的處理器可能用到不同的數據。***享內存 (shared memory)是 Unix下的多進程之間的通信方法 ,這種方法通常用於壹個程序的多進程間通信,實際上多個程序間也可以通過***享內存來傳遞信息。

***享內存的創建

***享內存是存在於內核級別的壹種資源,在shell中可以使用ipcs命令來查看當前系統IPC中的狀態,在文件系統/proc目錄下有對其描述的相應文件。函數shmget可以創建或打開壹塊***享內存區。函數原型如下: #include <sys/shm.h> int shmget( key_t key, size_t size, int flag ); 函數中參數key用來變換成壹個標識符,而且每壹個IPC對象與壹個key相對應。當新建壹個***享內存段時,size參數為要請求的內存長度(以字節為單位)。 註意:內核是以頁為單位分配內存,當size參數的值不是系統內存頁長的整數倍時,系統會分配給進程最小的可以滿足size長的頁數,但是最後壹頁的剩余部分內存是不可用的。 當打開壹個內存段時,參數size的值為0。參數flag中的相應權限位初始化ipc_perm結構體中的mode域。同時參數flag是函數行為參數,它指定壹些當函數遇到阻塞或其他情況時應做出的反應。shmid_ds結構初始化如表14-4所示。

編輯本段初始化

shmid_ds結構數據 初 值 shmid_ds結構數據 初 值

shm_lpid 0 shm_dtime 0

shm_nattach 0 shm_ctime 系統當前值

shm_atime 0 shm_segsz 參數 size

下面實例演示了使用shmget函數創建壹塊***享內存。程序中在調用shmget函數時指定key參數值為IPC_PRIVATE,這個參數的意義是創建壹個新的***享內存區,當創建成功後使用shell命令ipcs來顯示目前系統下***享內存的狀態。命令參數-m為只顯示***享內存的狀態。 (1)在vi編輯器中編輯該程序如下: 程序清單14-8 create_shm.c 使用shmget函數創建***享內存 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> #define BUFSZ 4096 int main ( void ) printf ( "successfully created segment : %d \n", shm_id ) ; system( "ipcs -m"); /*調用ipcs命令查看IPC*/ exit( 0 ); } (2)在shell中編譯該程序如下: $gcc create_shm.c–o create_shm (3)在shell中運行該程序如下: $./ create_shm successfully created segment : 2752516 ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 65536 root 600 393216 2 dest 0x00000000 2654209 root 666 4096 0 0x0056a4d5 2686978 root 600 488 1 0x0056a4d6 2719747 root 600 131072 1 0x00000000 2752516 root 666 4096 0 上述程序中使用shmget函數來創建壹段***享內存,並在結束前調用了系統shell命令ipcs –m來查看當前系統IPC狀態。

編輯本段***享內存的操作

由於***享內存這壹特殊的資源類型,使它不同於普通的文件,因此,系統需要為其提供專有的操作函數,而這無疑增加了程序員開發的難度(需要記憶額外的專有函數)。使用函數shmctl可以對***享內存段進行多種操作,其函數原型如下: #include <sys/shm.h> int shmctl( int shm_id, int cmd, struct shmid_ds *buf ); 函數中參數shm_id為所要操作的***享內存段的標識符,struct shmid_ds型指針參數buf的作用與參數cmd的值相關,參數cmd指明了所要進行的操作,其解釋如表14-5所示。

編輯本段cmd參數詳解

cmd的值 意 義

IPC_STAT 取shm_id所指向內存***享段的shmid_ds結構,對參數buf指向的結構賦值

IPC_SET 使用buf指向的結構對sh_mid段的相關結構賦值,只對以下幾個域有作用,shm_perm. uid shm_perm.gid以及shm_perm.mode 註意此命令只有具備以下條件的進程才可以請求: 1.進程的用戶ID等於shm_perm.cuid或者等於shm_perm.uid 2.超級用戶特權進程

IPC_RMID 刪除shm_id所指向的***享內存段,只有當shmid_ds結構的shm_nattch域為零時,才會真正執行刪除命令,否則不會刪除該段 註意此命令的請求規則與IPC_SET命令相同

SHM_LOCK 鎖定***享內存段在內存,此命令只能由超級用戶請求

SHM_UNLOCK 對***享內存段解鎖,此命令只能由超級用戶請求

使用函數shmat將壹個存在的***享內存段連接到本進程空間,其函數原型如下: #include <sys/shm.h> void *shmat( int shm_id, const void *addr, int flag ); 函數中參數shm_id指定要引入的***享內存,參數addr與flag組合說明要引入的地址值,通常只有2種用法,addr為0,表明讓內核來決定第1個可以引入的位置。addr非零,並且flag中指定SHM_RND,則此段引入到addr所指向的位置(此操作不推薦使用,因為不會只對壹種硬件上運行應用程序,為了程序的通用性推薦使用第1種方法),在flag參數中可以指定要引入的方式(讀寫方式指定)。 %說明:函數成功執行返回值為實際引入的地址,失敗返回–1。shmat函數成功執行會將shm_id段的shmid_ds結構的shm_nattch計數器的值加1。 當對***享內存段操作結束時,應調用shmdt函數,作用是將指定的***享內存段從當前進程空間中脫離出去。函數原型如下: #include <sys/shm.h> int shmdt( void *addr); 參數addr是調用shmat函數的返回值,函數執行成功返回0,並將該***享內存的shmid_ds結構的shm_nattch計數器減1,失敗返回–1。 下面實例演示了操作***享內存段的流程。程序的開始部分先檢測用戶是否有輸入,如出錯則打印該命令的使用幫助。接下來從命令行讀取將要引入的***享內存ID,使用shmat函數引入該***享內存,並在分離該內存之前睡眠3秒以方便查看系統IPC狀態。 (1)在vi編輯器中編輯該程序如下: 程序清單14-9 opr_shm.c 操作***享內存段 #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdlib.h> #include <stdio.h> int main ( int argc, char *argv[] ) shm_id = atoi(argv[1]); /*得到要引入的***享內存段*/ /*引入***享內存段,由內核選擇要引入的位置*/ if ( (shm_buf = shmat( shm_id, 0, 0)) < (char *) 0 ) printf ( " segment attached at %p\n", shm_buf ); /*輸出導入的位置*/ system("ipcs -m"); sleep(3); /* 休眠 */ if ( (shmdt(shm_buf)) < 0 ) printf ( "segment detached \n" ); system ( "ipcs -m " ); /*再次查看系統IPC狀態*/ exit ( 0 ); } (2)在shell中編譯該程序如下: $gcc opr_shm.c–o opr_shm (3)在shell中運行該程序如下: $./ opr_shm 2752516 segment attached at 0xb7f29000 ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 65536 root 600 393216 2 dest 0x00000000 2654209 root 666 4096 0 0x0056a4d5 2686978 root 600 488 1 0x0056a4d6 2719747 root 600 131072 1 0x00000000 2752516 root 666 4096 1 segment detached ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 65536 root 600 393216 2 dest 0x00000000 2654209 root 666 4096 0 0x0056a4d5 2686978 root 600 488 1 0x0056a4d6 2719747 root 600 131072 1 0x00000000 2752516 root 666 4096 0 上述程序中從命令行中讀取所要引入的***享內存ID,並使用shmat函數引入該內存到當前的進程空間中。註意在使用shmat函數時,將參數addr的值設為0,所表達的意義是由內核來決定該***享內存在當前進程中的位置。由於在編程的過程中,很少會針對某壹個特定的硬件或系統編程,所以由內核決定引入位置也就是shmat推薦的使用方式。在導入後使用shell命令ipcs –m來顯示當前的系統IPC的狀態,可以看出輸出信息中nattch字段為該***享內存時的引用值,最後使用shmdt函數分離該***享內存並打印系統IPC的狀態。

編輯本段***享內存使用註意事項

***享內存相比其他幾種方式有著更方便的數據控制能力,數據在讀寫過程中會更透明。當成功導入壹塊***享內存後,它只是相當於壹個字符串指針來指向壹塊內存,在當前進程下用戶可以隨意的訪問。缺點是,數據寫入進程或數據讀出進程中,需要附加的數據結構控制,***享內存通信數據結構示意如圖14-9所示。

編輯本段結構示意

%說明:圖中兩個進程同時遵循壹定的規則來讀寫該內存。同時,在多進程同步或互斥上也需要附加的代碼來輔助***享內存機制。 在***享內存段中都是以字符串的默認結束符為壹條信息的結尾。每個進程在讀寫時都遵守這個規則,就不會破壞數據的完整性。

另外,站長團上有產品團購,便宜有保證

  • 上一篇:編程實現將是其中數量最多的
  • 下一篇:會計專業畢業論文:淺談會計電算化
  • copyright 2024編程學習大全網