IPCの共有メモリ


共有メモリ
*最速のIPCは、操作共有メモリがプロセス-カーネルのデータコピーに関係しないからです.
*プロセス間の操作共有メモリは、信号量などの同期機構が必要です.
データ構造shmid_ds(萼include<sys/shm.h>)
struct shmid_ds{
    struct ipc_perm shm_perm;         /*     */
    int shm_segsz;                    /*    (      )*/
    time_t shm_atime;                 /*              */
    time_t shm_dtime;                 /*             */
    time_t shm_ctime;                 /*             */
    unsigned short shm_cpid;          /*       pid*/
    unsigned short shm_lpid;          /*         1    pid*/
    short shm_nattch;                 /*             */
    /*      */
    unsigned short shm_npages;        /*    (     )*/
    unsigned long *shm_pages;         /*  frames->SHMMAX     */
    struct vm_area_struct *attaches;  /*       */
};
相関関数
#include <sys/shm.h>
//      
int shmget(key_t key, size_t size, int shmflg)
//               
void *shmat(int shmid, const void *shmaddr, int shmflg)
//             
int shmdt(const void *shmaddr)
//     ,    
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
使用例
/*
 *         :
 * PS:                     
 *   (1  Int  ):   0.40S,    0.78S,    39.8S
 */
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
using namespace std;

class CSemLock
{
public:
    CSemLock(const char *pSemPath) 
    {
        key_t iSemKey;
        if ((iSemKey = ftok(pSemPath, 1)) == -1) {
            cout << "Ftok Err" << endl;
            exit(-1);
        }
        if ((iSemId = semget(iSemKey, 1, IPC_CREAT|IPC_EXCL|0666)) == (char *)-1) {
            cout << "Semget Err" << endl;
            exit(-1);
        }
        UnLock();
    }
    ~CSemLock() 
    {
        if (semctl(iSemId, 0, IPC_RMID) == -1) {
            cout << "Semctl Err" << endl;
            exit(-1);
        }
    }
public:
    void Lock()
    {
        struct sembuf sSem;
        sSem.sem_num = 0;
        sSem.sem_op = -1;
        sSem.sem_flg = 0;
        semop(iSemId, &sSem, 1);
    }
    void UnLock() 
    {
        struct sembuf sSem;
        sSem.sem_num = 0;
        sSem.sem_op = 1;
        sSem.sem_flg = 0;
        semop(iSemId, &sSem, 1);
    }
private:
    key_t iSemKey;
    int iSemId;
    struct sembuf sSem;
};

int main()
{
    key_t iShmKey;
    int iShmId;

    // Get Shm Key
    const char *pShmPath = "/data/home/andyawang/code/ipc/Shm";
    if ((iShmKey = ftok(pShmPath, 1)) == -1) {
        cout << "Ftok Err" << endl;
        return -1;
    }

    // 1.shmget():      
	// int shmget(key_t key, size_t size, int shmflg)
	// key		:IPC Key 
	// size		:0   ,>0          (Byte)
	// shmflg	:0   ,IPC_CREAT       ,IPC_CREAT|IPC_EXCL      ,       ,      -1 
    if ((iShmId = shmget(iShmKey, 4096, IPC_CREAT|IPC_EXCL|0666)) == -1) {
        cout << "Shmget Err" << endl;
        return -1;
    }

    // 2.shmat():               
	// void *shmat(int shmid, const void *shmaddr, int shmflg)
	// shmid	:   Id
	// shmaddr	:                  ,   NULL,         
	// shmflg	:SHM_RDONLY     ,       
    char* pShm;
    if ((pShm = (char*)shmat(iShmId, NULL, 0)) == (char*)-1) {
        cout << "Shmat Err" << endl;
        return -1;
    }

    // Operation Shm
    CSemLock mSemLock("/data/home/andyawang/code/ipc/Sem");
    struct timeval tvBegin, tvEnd;
    gettimeofday(&tvBegin, NULL);
    for(int i = 0; i < 100000000; i ++)
    {
        mSemLock.Lock();
        int *pVal = (int *)pShm;
        (*pVal) ++;
        mSemLock.UnLock();
    }
    gettimeofday(&tvEnd, NULL);
    cout << "Shm Val : " << *(int *)pShm << endl;
    cout << "Use Second : " << (tvEnd.tv_sec-tvBegin.tv_sec)+1.0*(tvEnd.tv_usec-tvBegin.tv_usec)/1000000<< endl;

    // 3.shmctl():    ,    
	// int shmctl(int shmid, int cmd, struct shmid_ds *buf)
	// shmid	:   Id
	// cmd		:IPC_STAT        buf,IPC_SET  buf      ,IPC_RMID   
	// buf		:         
    if (shmctl(iShmId, IPC_RMID, NULL) == -1) {
        cout << "Shmctl Err" << endl;
        return -1;
    }

    return 0;
}