UNIX环境高级编程学习之第十五章进程间通信 – 系统V 共享内存使用(使用信号灯保护共享内存)

Linux/Unix C/C++ xiujie 193℃ 0评论 已收录

UNIX环境高级编程学习之第十五章进程间通信 – 系统V 共享内存使用(使用信号灯保护共享内存)

/* 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;
}


喜欢 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址