Linux共享内存(二)
生活随笔
收集整理的這篇文章主要介紹了
Linux共享内存(二)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Linux共享內(nèi)存編程實(shí)例
原文鏈接:http://blog.csdn.net/pcliuguangtao/article/details/6526119
/*共享內(nèi)存允許兩個(gè)或多個(gè)進(jìn)程進(jìn)程共享同一塊內(nèi)存(這塊內(nèi)存會(huì)映射到各個(gè)進(jìn)程自己獨(dú)立的地址空間)從而使得這些進(jìn)程可以相互通信。在GNU/Linux中所有的進(jìn)程都有唯一的虛擬地址空間,而共享內(nèi)存應(yīng)用編程接口API允許一個(gè)進(jìn)程使用公共內(nèi)存區(qū)段。但是對(duì)內(nèi)存的共享訪問其復(fù)雜度也相應(yīng)增加。共享內(nèi)存的優(yōu)點(diǎn)是簡(jiǎn)易性。使用消息隊(duì)列時(shí),一個(gè)進(jìn)程要向隊(duì)列中寫入消息,這要引起從用戶地址空間向內(nèi)核地址空間的一次復(fù)制,同樣一個(gè)進(jìn)程進(jìn)行消息讀取時(shí)也要進(jìn)行一次復(fù)制。共享內(nèi)存的優(yōu)點(diǎn)是完全省去了這些操作。共享內(nèi)存會(huì)映射到進(jìn)程的虛擬地址空間,進(jìn)程對(duì)其可以直接訪問,避免了數(shù)據(jù)的復(fù)制過程。因此,共享內(nèi)存是GNU/Linux現(xiàn)在可用的最快速的IPC機(jī)制。進(jìn)程退出時(shí)會(huì)自動(dòng)和已經(jīng)掛接的共享內(nèi)存區(qū)段分離,但是仍建議當(dāng)進(jìn)程不再使用共享區(qū)段時(shí)調(diào)用shmdt來卸載區(qū)段。注意,當(dāng)一個(gè)進(jìn)程分支出父進(jìn)程和子進(jìn)程時(shí),父進(jìn)程先前創(chuàng)建的所有共享內(nèi)存區(qū)段都會(huì)被子進(jìn)程繼承。如果區(qū)段已經(jīng)做了刪除標(biāo)記(在前面以IPC——RMID指令調(diào)用shmctl),而當(dāng)前掛接數(shù)已經(jīng)變?yōu)?,這個(gè)區(qū)段就會(huì)被移除。*/ /*shmget( ) 創(chuàng)建一個(gè)新的共享內(nèi)存區(qū)段取得一個(gè)共享內(nèi)存區(qū)段的描述符shmctl( ) 取得一個(gè)共享內(nèi)存區(qū)段的信息為一個(gè)共享內(nèi)存區(qū)段設(shè)置特定的信息移除一個(gè)共享內(nèi)存區(qū)段shmat( ) 掛接一個(gè)共享內(nèi)存區(qū)段shmdt( ) 于一個(gè)共享內(nèi)存區(qū)段的分離*/ //創(chuàng)建一個(gè)共享內(nèi)存區(qū)段,并顯示其相關(guān)信息,然后刪除該內(nèi)存共享區(qū) #include <stdio.h> #include <unistd.h> //getpagesize( ) #include <sys/ipc.h> #include <sys/shm.h> #define MY_SHM_ID 67483 int main( ){//獲得系統(tǒng)中頁(yè)面的大小printf( "page size=%d/n",getpagesize( ) );//創(chuàng)建一個(gè)共享內(nèi)存區(qū)段int shmid,ret;shmid=shmget( MY_SHM_ID,4096,0666|IPC_CREAT );//創(chuàng)建了一個(gè)4KB大小共享內(nèi)存區(qū)段。指定的大小必須是當(dāng)前系統(tǒng)架構(gòu)//中頁(yè)面大小的整數(shù)倍if( shmid>0 )printf( "Create a shared memory segment %d/n",shmid );//獲得一個(gè)內(nèi)存區(qū)段的信息struct shmid_ds shmds;//shmid=shmget( MY_SHM_ID,0,0 );//示例怎樣獲得一個(gè)共享內(nèi)存的標(biāo)識(shí)符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" );}//刪除該共享內(nèi)存區(qū)ret=shmctl( shmid,IPC_RMID,0 );if( ret==0 )printf( "Shared memory removed /n" );elseprintf( "Shared memory remove failed /n" );return 0;}//共享內(nèi)存區(qū)段的掛載,脫離和使用 //理解共享內(nèi)存區(qū)段就是一塊大內(nèi)存 #include <stdio.h> #include <sys/shm.h> #include <sys/ipc.h> #include <errno.h> #define MY_SHM_ID 67483 int main( ){//共享內(nèi)存區(qū)段的掛載和脫離int shmid,ret;void* mem;shmid=shmget( MY_SHM_ID,0,0 );if( shmid>=0 ){mem=shmat( shmid,( const void* )0,0 );//shmat()返回進(jìn)程地址空間中指向區(qū)段的指針if( ( int )mem!=-1 ){printf( "Shared memory was attached in our address space at %p/n",mem );//向共享區(qū)段內(nèi)存寫入數(shù)據(jù)strcpy( ( char* )mem,"This is a test string./n" );printf( "%s/n",(char*)mem );//脫離共享內(nèi)存區(qū)段ret=shmdt( mem );if( ret==0 )printf( "Successfully detached memory /n" );elseprintf( "Memory detached failed %d/n",errno );}elseprintf( "shmat( ) failed/n" );}elseprintf( "shared memory segment not found/n" );return 0;} /*內(nèi)存共享區(qū)段與旗語(yǔ)和消息隊(duì)列不同,一個(gè)區(qū)段可以被鎖定。被鎖定的區(qū)段不允許被交換出內(nèi)存。這樣做的優(yōu)勢(shì)在于,與其把內(nèi)存區(qū)段交換到文件系統(tǒng),在某個(gè)應(yīng)用程序調(diào)用時(shí)再交換回內(nèi)存,不如讓它一直處于內(nèi)存中,且對(duì)多個(gè)應(yīng)用程序可見。從提升性能的角度來看,很重要的。*/ int shmid; //... shmid=shmget( MY_SHM_ID,0,0 ); ret=shmctl( shmid,SHM_LOCK,0 ); if( ret==0 )printf( "Locked!/n" );/*使用旗語(yǔ)協(xié)調(diào)共享內(nèi)存的例子使用和編譯命令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 commandif( argc>=2 ){//create the shared memory segment and init it//with the semaphoreif( !strncmp(argv[ 1 ],"create",6) ){//create the shared memory segment and semaphoreprintf( "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 initblock->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 segmentshmdt( ( 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 bufferif( argc<3 ) exit( -1 );user=( char )argv[ 2 ][ 0 ];//grab the segmentshmid=shmget( MY_SHM_ID,0,0 );block=( MY_BLOCK_T* )shmat( shmid,( const void* )0,0 );/*##########重點(diǎn)就是使用旗語(yǔ)對(duì)共享區(qū)的訪問###########*/for( i=0;i<100;++i ){sleep( 1 ); //設(shè)置成1s就會(huì)看到 a/b交替出現(xiàn),為0則a和b連續(xù)出現(xiàn)//grab the semaphoresb.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 SECTIONblock->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" );}elseprintf( "Failed to acquire the semaphore/n" );}//do some clear workret=shmdt(( void*)block);}else if( !strncmp(argv[ 1 ],"read",4) ){//here we will read the buffer in the shared segmentshmid=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 );}elseprintf( "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 semaphoreret=semctl( block->semID,0,IPC_RMID );if( ret==0 )printf( "Successfully remove the semaphore /n" );//remove the shared segmentret=shmctl( shmid,IPC_RMID,0 );if( ret==0 )printf( "Successfully remove the segment /n" );}}elseprintf( "Unkonw command/n" );}return 0;}?
總結(jié)
以上是生活随笔為你收集整理的Linux共享内存(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [OS][FS]查看ext3文件系统分区
- 下一篇: Linux驱动之混杂设备(misc)