Linux共用記憶體(二)

來源:互聯網
上載者:User

轉自:http://www.cnblogs.com/hicjiajia/archive/2012/05/17/2506638.html

/*共用記憶體允許兩個或多個進程進程共用同一塊記憶體(這塊記憶體會映射到各個進程自己獨立的地址空間)  從而使得這些進程可以相互連信。  在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 67483int 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 67483int 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 200typedef 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;            }
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.