UNIX環境高級編程學習之第十五章進程間通信 - 系統V 共享內存使用(使用信號燈保護共享內存)

UNIX環境高級編程學習之第十五章進程間通信 - 系統V 共享內存使用(使用信號燈保護共享內存)

 

 

 

CSDN Blog又出問題了,不能插入代碼了。只能這麼粘貼了。

 

 



/* User:Lixiujie      
 * Date:20100915
 * Desc:系統V 共享內存使用(使用信號燈保護共享內存)
 * File:shared_memory.c
 * System:Ubuntu 64bit
 * gcc shared_memory.c -o shm
 */ 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <unistd.h> 
#include <errno.h> 
#include <sys/types.h> 
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
union semun {
    int val;                    /* value for SETVAL */
    struct semid_ds *buf;        /* buffer for IPC_STAT & IPC_SET */
    unsigned short *array;        /* array for GETALL & SETALL */
    struct seminfo *__buf;        /* buffer for IPC_INFO */   //test!!
    void *__pad;
};
/* 取當前文件路徑 */ 
char* getCurrentFilePath(char *szCurrentFilePath);
/* 創建信號燈 */
int CreateSemaphore(const char* szFilePath, int id);
/* 申請使用資源 */
int PSemaphore(int semID);
/* 釋放資源 */
int VSemaphore(int semID);
/* 刪除信號量*/
int RemoveSemaphore(int semID);

/* 創建共享內存 */
int CreateSharedMemory(const char* szFilePath, int id, int iSize);
/* 附加共享內存 */
void* AttachSharedMemory(int shmID);
/* 分離共享內存 */
int DetachSharedMemory(void* pData);
/* 共享內存讀操作 */
void* ReadSharedMemory(int iShmStart,int iShmLen, void* pData, int semID,int shmID);
/* 共享內存寫操作 */
void* WriteSharedMemory(int iShmStart, int iLen, void* pData, int semID,int shmID);
/* 刪除共享內存 */
int RemoveSharedMemory(int shmID);

/* 取當前文件路徑 */ 
char* getCurrentFilePath(char *szCurrentFilePath){ 
    char szBuf[256] = { 0x00 }; 
    strcpy(szBuf, __FILE__); 
    if (strstr(szBuf, "/") == NULL){ 
        memset(szBuf, 0x00, sizeof(szBuf)); 
        strcpy(szBuf, getenv("PWD")); 
        strcat(szBuf, "/"); 
        strcat(szBuf, __FILE__); 
    } 
    strcpy(szCurrentFilePath, szBuf); 
    return szCurrentFilePath; 
}

/* 創建信號燈 */
int CreateSemaphore(const char* szFilePath, int id){
    int i;
    /* 信號燈的Key */
    key_t semKey;
    union semun arg;
    int semID;
    int tmpErrno;
    /* 等待信號集初始化完成嘗試次數 */
    int iMaxTries = 3;
    /* 信號集初始化完成標誌 */
    int iInitOk = 0;
    /* 當前信號集信息, 內核分配給每個信號集的結構 */
    struct semid_ds semCurrInfo;
    /* 產生key */ 
    semKey = ftok(szFilePath, id);
    if (-1 == semKey){ 
        perror("CreateSemaphore() ftok() is failed!/n"); 
        exit(1); 
    }
     /* 創建一個信號量集,只包含一個信號 */
    semID = semget(semKey, 1, IPC_CREAT|IPC_EXCL|00666);
    if (-1 == semID){
        tmpErrno = errno;
        if (EEXIST == tmpErrno){
            perror("CreateSemaphore() semget() is already exists!/n");
            /* 獲取一個信號量集,只包含一個信號 */
            semID = semget(semKey, 1, IPC_CREAT|00666);
            if (-1 == semID){
                perror("CreateSemaphore() semget() semget() is failed!/n");
                exit(1);
            }
            arg.buf = &semCurrInfo;
            for (i = 0;i < iMaxTries;i++){
                if (semctl(semID, 0, IPC_STAT, arg) == -1){
                    perror("CreateSemaphore() semget() semget() is failed!/n");
                }else{
                    /* sem_otime:最後semop修改時間,創建初始值爲0 */
                    if (arg.buf->sem_otime != 0){
                        iInitOk = 1;
                        break;
                    }
                }
                sleep(1);
            }
            if (0 == iInitOk){
                /* 第一個創建semaphore進程沒有初始化完成或剛好初始化完成,
                 * 本次要初始化一下,否則無法下面的工作。
                 */
                arg.val = 1;/* 資源數 */
                if (semctl(semID, 0, SETVAL, arg) == -1){
                    perror("CreateSemaphore() semget() semctl() is failed/n");
                    exit(-1);
                }
            }
        } else {
            perror("CreateSemaphore() semget() is failed!/n");
            exit(1);
        }
       
    }else{
         arg.val = 1;/* 資源數 */
        if (semctl(semID, 0, SETVAL, arg) == -1){
            perror("CreateSemaphore() semctl() is failed/n");
            exit(-1);
        }
    }
    return semID;
}

/* 申請使用資源 */
int PSemaphore(int semID){
    struct sembuf sops={0, -1, SEM_UNDO};
    return semop(semID, &sops, 1);
}

/* 釋放資源 */
int VSemaphore(int semID){
    struct sembuf sops={0, 1, SEM_UNDO};
    return semop(semID, &sops, 1);
}

/* 創建共享內存 */
int CreateSharedMemory(const char* szFilePath, int id, int iSize){
    /* 共享內存的Key */
    key_t shmKey;
    int shmID;
    int tmpErrno;
    /* 產生key */ 
    shmKey = ftok(szFilePath, id);
    if (-1 == shmKey){ 
        perror("CreateSharedMemory() ftok() is failed!/n"); 
        exit(1); 
    }
    /* 獲取一個共享內存 */
    shmID = shmget(shmKey, iSize, IPC_CREAT|IPC_EXCL|00666);
    if (-1 == shmID){
        tmpErrno = errno;
        if (EEXIST == tmpErrno){
            perror("CreateSharedMemory() shmget() is already exists!/n");
            /* 獲取一個共享內存 */
            shmID = shmget(shmKey, iSize, IPC_CREAT|00666);
            if (-1 == shmID){
                perror("CreateSharedMemory() shmget() shmget() is failed!/n");
                exit(1);
            }
        } else {
            perror("CreateSharedMemory() shmget() is failed!/n");
            exit(1);
        }
    }else{
        /* 初始化 */
        char* pC = (char*)AttachSharedMemory(shmID);
        if (pC == NULL){
            perror("CreateSharedMemory() AttachSharedMemory() is failed!/n");
            exit(1);
        }
        memset(pC, '/0',iSize);
        if (DetachSharedMemory(pC) != 0){
            perror("CreateSharedMemory() DetachSharedMemory() is failed!/n");
            exit(1);
        }
    }
    return shmID;
}

/* 附加共享內存 */
void* AttachSharedMemory(int shmID){
    char* pC;
    pC = (char*)shmat(shmID, NULL, 0);
    if (NULL == pC || pC == (char*)-1 ){
        return (void*)NULL;
    }
    return (void*)pC;
}

/* 分離共享內存 */
int DetachSharedMemory(void* pData){
    return shmdt(pData);
}

/* 共享內存讀操作 */
void* ReadSharedMemory(int iShmStart,int iShmLen, void* pData, int semID,int shmID){
    char *pC;
    int ret;
    ret = PSemaphore(semID);
    if (ret != 0){
        perror("ReadSharedMemory() PSemaphore() is failed!");
        return NULL;
    }
    pC = (char*)AttachSharedMemory(shmID);
    if (pC != NULL){
        memcpy(pData, pC+iShmStart, iShmLen);
        DetachSharedMemory(pC);
    }else{
        perror("ReadSharedMemory() AttachSharedMemory() is failed!");
        VSemaphore(semID);
        return NULL;
    }
    ret = VSemaphore(semID);
    if (ret != 0){
        perror("ReadSharedMemory() VSemaphore() is failed!");
        return NULL;
    }
    return pData;
}

/* 共享內存寫操作 */
void* WriteSharedMemory(int iShmStart, int iLen, void* pData, int semID,int shmID){
    char *pC;
    int ret;
    ret = PSemaphore(semID);
    if (ret != 0){
        perror("WriteSharedMemory() PSemaphore() is failed!");
        return NULL;
    }
    pC = (char*)AttachSharedMemory(shmID);
    if (pC != NULL){
        memcpy(pC+iShmStart, pData, iLen);
        DetachSharedMemory(pC);
    }else{
        perror("WriteSharedMemory() AttachSharedMemory() is failed!");
        VSemaphore(semID);
        return NULL;
    }
    ret = VSemaphore(semID);
    if (ret != 0){
        perror("WriteSharedMemory() VSemaphore() is failed!");
        return NULL;
    }
    return pData;
}

/* 刪除共享內存 */
int RemoveSharedMemory(int shmID){
    return shmctl(shmID, IPC_RMID, NULL);
}

/* 刪除信號量*/
int RemoveSemaphore(int semID){
    return semctl(semID, 0, IPC_RMID);
}

int main(int argc, char * argv[]){
    char *pC;
    char szFilePath[256] = {  '/0' };
    char szData[256] = { 0x00 };
    getCurrentFilePath(szFilePath);
    int semID; /* 信號量,二值信號燈 相當於進程間互斥鎖 */
    int shmID; /* 共享內存 */
    /* 創建或獲取信號量 */
    semID = CreateSemaphore(szFilePath, 0);
    /* 創建或獲取共享內存 */
    shmID = CreateSharedMemory(szFilePath, 0, 4096);
    /* 讀共存內存數據 */
    memset(szData, 0x00, sizeof(szData));
    pC = ReadSharedMemory(0, sizeof(szData) - 1, szData, semID, shmID);
    if (NULL == pC){
        perror("main() ReadSharedMemory() is failed!");
        exit(-1);
    }
    printf("Data_1:%s/n", szData);
    memset(szData, 0x00, sizeof(szData));
    pC = ReadSharedMemory(300, sizeof(szData) - 1, szData, semID, shmID);
    if (NULL == pC){
        perror("main() ReadSharedMemory() is failed!");
        exit(-1);
    }
    printf("Data_2:%s/n", szData);
    /* 寫共存內存數據 */
    memset(szData, 0x00, sizeof(szData));
    strcpy(szData, "Hello lixiujie!/0");
    pC = WriteSharedMemory(0, sizeof(szData) - 1, szData, semID, shmID);
    if (NULL == pC){
        perror("main() WriteSharedMemory() is failed!");
        exit(-1);
    }
    strcpy(szData, "Hello wanzhenjie!/0");
    pC = WriteSharedMemory(300, sizeof(szData) - 1, szData, semID, shmID);
    if (NULL == pC){
        perror("main() WriteSharedMemory() is failed!");
        exit(-1);
    }
   
    sleep(20);

    /* 讀共存內存數據 */
    memset(szData, 0x00, sizeof(szData));
    pC = ReadSharedMemory(0, sizeof(szData) - 1, szData, semID, shmID);
    if (NULL == pC){
        perror("main() ReadSharedMemory() is failed!");
        exit(-1);
    }
    printf("Data_1:%s/n", szData);
    memset(szData, 0x00, sizeof(szData));
    pC = ReadSharedMemory(300, sizeof(szData) - 1, szData, semID, shmID);
    if (NULL == pC){
        perror("main() ReadSharedMemory() is failed!");
        exit(-1);
    }
    printf("Data_2:%s/n", szData);

    RemoveSharedMemory(shmID);
    RemoveSemaphore(semID);
    return 0;
}

 



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章