Linux共享記憶體(二)
Linux共享記憶體程式設計例項
原文連結:http://blog.csdn.net/pcliuguangtao/article/details/6526119
/*共享記憶體允許兩個或多個程式程式共享同一塊記憶體(這塊記憶體會對映到各個程式自己獨立的地址空間) 從而使得這些程式可以相互通訊。 在GNU/Linux中所有的程式都有唯一的虛擬地址空間,而共享記憶體應用程式設計介面API允許一個程式使 用公共記憶體區段。但是對記憶體的共享訪問其複雜度也相應增加。共享記憶體的優點是簡易性。 使用訊息佇列時,一個程式要向佇列中寫入訊息,這要引起從使用者地址空間向核心地址空間的一次複製, 同樣一個程式進行訊息讀取時也要進行一次複製。共享記憶體的優點是完全省去了這些操作。 共享記憶體會對映到程式的虛擬地址空間,程式對其可以直接訪問,避免了資料的複製過程。 因此,共享記憶體是GNU/Linux現在可用的最快速的IPC機制。 程式退出時會自動和已經掛接的共享記憶體區段分離,但是仍建議當程式不再使用共享區段時 呼叫shmdt來解除安裝區段。 注意,當一個程式分支出父程式和子程式時,父程式先前建立的所有共享記憶體區段都會被子程式繼承。 如果區段已經做了刪除標記(在前面以IPC——RMID指令呼叫shmctl),而當前掛接數已經變為0, 這個區段就會被移除。 */ /* shmget( ) 建立一個新的共享記憶體區段 取得一個共享記憶體區段的描述符 shmctl( ) 取得一個共享記憶體區段的資訊 為一個共享記憶體區段設定特定的資訊 移除一個共享記憶體區段 shmat( ) 掛接一個共享記憶體區段 shmdt( ) 於一個共享記憶體區段的分離 */ //建立一個共享記憶體區段,並顯示其相關資訊,然後刪除該記憶體共享區 #include <stdio.h> #include <unistd.h> //getpagesize( ) #include <sys/ipc.h> #include <sys/shm.h> #define MY_SHM_ID 67483 int main( ) { //獲得系統中頁面的大小 printf( "page size=%d/n",getpagesize( ) ); //建立一個共享記憶體區段 int shmid,ret; shmid=shmget( MY_SHM_ID,4096,0666|IPC_CREAT ); //建立了一個4KB大小共享記憶體區段。指定的大小必須是當前系統架構 //中頁面大小的整數倍 if( shmid>0 ) printf( "Create a shared memory segment %d/n",shmid ); //獲得一個記憶體區段的資訊 struct shmid_ds shmds; //shmid=shmget( MY_SHM_ID,0,0 );//示例怎樣獲得一個共享記憶體的識別符號 ret=shmctl( shmid,IPC_STAT,&shmds ); if( ret==0 ) { printf( "Size of memory segment is %d/n",shmds.shm_segsz ); printf( "Numbre of attaches %d/n",( int )shmds.shm_nattch ); } else { printf( "shmctl( ) call failed/n" ); } //刪除該共享記憶體區 ret=shmctl( shmid,IPC_RMID,0 ); if( ret==0 ) printf( "Shared memory removed /n" ); else printf( "Shared memory remove failed /n" ); return 0; } //共享記憶體區段的掛載,脫離和使用 //理解共享記憶體區段就是一塊大記憶體 #include <stdio.h> #include <sys/shm.h> #include <sys/ipc.h> #include <errno.h> #define MY_SHM_ID 67483 int main( ) { //共享記憶體區段的掛載和脫離 int shmid,ret; void* mem; shmid=shmget( MY_SHM_ID,0,0 ); if( shmid>=0 ) { mem=shmat( shmid,( const void* )0,0 ); //shmat()返回程式地址空間中指向區段的指標 if( ( int )mem!=-1 ) { printf( "Shared memory was attached in our address space at %p/n",mem ); //向共享區段記憶體寫入資料 strcpy( ( char* )mem,"This is a test string./n" ); printf( "%s/n",(char*)mem ); //脫離共享記憶體區段 ret=shmdt( mem ); if( ret==0 ) printf( "Successfully detached memory /n" ); else printf( "Memory detached failed %d/n",errno ); } else printf( "shmat( ) failed/n" ); } else printf( "shared memory segment not found/n" ); return 0; } /*記憶體共享區段與旗語和訊息佇列不同,一個區段可以被鎖定。 被鎖定的區段不允許被交換出記憶體。這樣做的優勢在於,與其 把記憶體區段交換到檔案系統,在某個應用程式呼叫時再交換回記憶體, 不如讓它一直處於記憶體中,且對多個應用程式可見。從提升效能的角度 來看,很重要的。 */ int shmid; //... shmid=shmget( MY_SHM_ID,0,0 ); ret=shmctl( shmid,SHM_LOCK,0 ); if( ret==0 ) printf( "Locked!/n" ); //////////////////////////////////////////////////////////////////////// /*使用旗語協調共享記憶體的例子 使用和編譯命令 gcc -Wall test.c -o test ./test create ./test use a & ./test use b & ./test read & ./test remove */ #include <stdio.h> #include <sys/shm.h> #include <sys/ipc.h> #include <sys/sem.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #define MY_SHM_ID 34325 #define MY_SEM_ID 23234 #define MAX_STRING 200 typedef struct { int semID; int counter; char string[ MAX_STRING+1 ]; }MY_BLOCK_T; int main(int argc,char** argv) { int shmid,ret,i; MY_BLOCK_T* block; struct sembuf sb; char user; //make sure there is a command if( argc>=2 ) { //create the shared memory segment and init it //with the semaphore if( !strncmp(argv[ 1 ],"create",6) ) { //create the shared memory segment and semaphore printf( "Creating the shared memory/n" ); shmid=shmget( MY_SHM_ID,sizeof( MY_BLOCK_T ),( IPC_CREAT|0666 ) ); block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); block->counter=0; //create the semaphore and init block->semID=semget(MY_SEM_ID,1,( IPC_CREAT|0666 )); sb.sem_num=0; sb.sem_op=1; sb.sem_flg=0; semop( block->semID,&sb,1 ); //now detach the segment shmdt( ( void* )block ); printf( "Create the shared memory and semaphore successuflly/n" ); } else if( !strncmp(argv[ 1 ],"use",3) ) { /*use the segment*/ //must specify also a letter to write to the buffer if( argc<3 ) exit( -1 ); user=( char )argv[ 2 ][ 0 ]; //grab the segment shmid=shmget( MY_SHM_ID,0,0 ); block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); /*##########重點就是使用旗語對共享區的訪問###########*/ for( i=0;i<100;++i ) { sleep( 1 ); //設定成1s就會看到 a/b交替出現,為0則a和b連續出現 //grab the semaphore sb.sem_num=0; sb.sem_op=-1; sb.sem_flg=0; if( semop( block->semID,&sb,1 )!=-1 ) { //write the letter to the segment buffer //this is our CRITICAL SECTION block->string[ block->counter++ ]=user; sb.sem_num=0; sb.sem_op=1; sb.sem_flg=0; if( semop( block->semID,&sb,1 )==-1 ) printf( "Failed to release the semaphore/n" ); } else printf( "Failed to acquire the semaphore/n" ); } //do some clear work ret=shmdt(( void*)block); } else if( !strncmp(argv[ 1 ],"read",4) ) { //here we will read the buffer in the shared segment shmid=shmget( MY_SHM_ID,0,0 ); if( shmid!=-1 ) { block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); block->string[ block->counter+1 ]=0; printf( "%s/n",block->string ); printf( "Length=%d/n",block->counter ); ret=shmdt( ( void*)block ); } else printf( "Unable to read segment/n" ); } else if( !strncmp(argv[ 1 ],"remove",6) ) { shmid=shmget( MY_SHM_ID,0,0 ); if( shmid>=0 ) { block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 ); //remove the semaphore ret=semctl( block->semID,0,IPC_RMID ); if( ret==0 ) printf( "Successfully remove the semaphore /n" ); //remove the shared segment ret=shmctl( shmid,IPC_RMID,0 ); if( ret==0 ) printf( "Successfully remove the segment /n" ); } } else printf( "Unkonw command/n" ); } return 0; }
相關文章
- [Linux]共享記憶體Linux記憶體
- Linux共享記憶體的管理Linux記憶體
- Linux:深入淺出 Linux 共享記憶體Linux記憶體
- linux記憶體管理(二)- vmallocLinux記憶體
- Linux程式間通訊之共享記憶體Linux記憶體
- POSIX 共享記憶體記憶體
- Golang 共享記憶體Golang記憶體
- Linux 程式設計1:深入淺出 Linux 共享記憶體Linux程式設計記憶體
- linux mmap應用與驅動共享記憶體Linux記憶體
- QT之共享記憶體QT記憶體
- Qt共享記憶體QSharedMemoryQT記憶體
- nginx共享記憶體分析Nginx記憶體
- Linux 程式間通訊之System V 共享記憶體Linux記憶體
- Linux系統程式設計—共享記憶體之mmapLinux程式設計記憶體
- linux記憶體管理(十)- 頁面回收(二)Linux記憶體
- 共享記憶體對映(linux程式與執行緒學習筆記)記憶體Linux執行緒筆記
- Linux系統程式設計之命名管道與共享記憶體Linux程式設計記憶體
- 【記憶體管理】Oracle如何使用ASMM自動共享記憶體管理記憶體OracleASM
- nginx中共享記憶體的使用Nginx記憶體
- Android匿名共享記憶體(Ashmem)原理Android記憶體
- linux記憶體管理(一)實體記憶體的組織和記憶體分配Linux記憶體
- OpenResty 和 Nginx 的共享記憶體區是如何消耗實體記憶體的RESTNginx記憶體
- Linux實體記憶體管理Linux記憶體
- 程序間通訊(3)-共享記憶體記憶體
- 程式間通訊之共享記憶體記憶體
- Kubernetes中Pod間共享記憶體方案記憶體
- Linux 虛擬記憶體Linux記憶體
- system-v IPC共享記憶體通訊記憶體
- PostgreSQL共享記憶體裡的內容(initCommunication)SQL記憶體
- Golang併發之共享記憶體變數Golang記憶體變數
- [20190104]ipcs檢視共享記憶體段.txt記憶體
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- Linux記憶體子系統——Locking Pages(記憶體鎖定)Linux記憶體
- 如何檢視linux系統中空閒記憶體/實體記憶體使用/剩餘記憶體Linux記憶體
- Windows記憶體管理分析(二)Windows記憶體
- Linux 記憶體區管理 slabLinux記憶體
- Linux記憶體、Swap、Cache、BufferLinux記憶體
- C++ 共享記憶體ShellCode跨程式傳輸C++記憶體