進程共享同內存

/**
 * 所有進程共享同一塊內存,共享內存在各種進程間通信方式中具有最高的效率。
 * 訪問共享內存區域和訪問進程獨有的內存區域一樣快,並不需要通過系統調用或者其它需要切入內核的過程來完成
 * 優缺:共享內存塊提供了在任意數量的進程之間進行高效雙向通信的機制。每個使用者都可以讀取寫入數據,
 *    但是所有程序之間必須達成並遵守一定的協議,以防止諸如在讀取信息之前覆寫內存空間等競爭狀態的出現。
 *    不幸的是,Linux無法嚴格保證提供對共享內存塊的獨佔訪問,甚至是在您通過使用IPC_PRIVATE創建新的共享內存塊的時候也不能保證訪問的獨佔性。
 *     同時,多個使用共享內存塊的進程之間必須協調使用同一個鍵值。(可通過信號量來確保數據一致性)
 */
/*共享內存允許兩個或多個進程進程共享同一塊內存(這塊內存會映射到各個進程自己獨立的地址空間)
  從而使得這些進程可以相互通信。
  在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;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章