UNIX环境高级编程学习之第十五章进程间通信 – 系统V 共享内存使用(使用信号灯保护共享内存)
[code lang=”cpp”]/* 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;
}

[/code]

发表评论