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