헤더파일 : MultiProcessWithSemaphore.h
/******************************************************************************* * MultiProcessWithSemaphore.h * * * * IDENTIFICATION & REVISION * $Id$ * * NOTES * * ******************************************************************************/ /** * @file MultiProcessWithSemaphore.h * @brief 세마포어를 이용한 멀티 프로세스 큐 * 헤더파일 */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/shm.h> #include <semaphore.h> #include <fcntl.h> #include <time.h> #define KEY_ID 9300 #define SIZE 8192 #define PROCESS_COUNT 10 #define DATA_MAX_COUNT 5 #define STL_SUCCESS 0 #define STL_FAILURE 1 #define STL_TRY_THROW( aExpression, aLabel ) \ do \ { \ if( !(aExpression) ) \ { \ goto aLabel; \ } \ } while( 0 ) #define STL_CATCH( aLabel ) \ goto STL_FINISH_LABEL; \ aLabel: #define STL_FINISH \ STL_FINISH_LABEL: typedef struct qNode { int mData; struct qNode * mPrevNode; struct qNode * mNextNode; } qNode; typedef struct qQueue { qNode * mFrontNode; qNode * mRearNode; } qQueue; typedef struct qStruct { qQueue mQueue; void * mShmAddr; int mCount; sem_t mSemaphore; } qStruct; void * qInitialize( qStruct * aStruct ); void * qEnqueue( qStruct * aStruct, int aProcessId ); void * qDequeue( qStruct * aStruct, int aProcessId );
소스파일 : MultiProcessWithSemaphore.c
/******************************************************************************* * MultiProcessWithSemaphore.c * * * * IDENTIFICATION & REVISION * $Id$ * * NOTES * * ******************************************************************************/ /** * @file MultiProcessWithSemaphore.c * @brief 세마포어를 이용한 멀티 프로세스 큐 */ #include "MultiProcessWithSemaphore.h" void * gShmAddrStart; int main() { pid_t sProcessId[PROCESS_COUNT]; void * sShmAddr = NULL; int sShmId = 0; int sIsDetachShm = 0; int sIsRemoveShm = 0; int sRepeatCount = 0; int sStatus = 0; int sStructSize = 0; int sNodeSize = 0; qStruct * sStruct = NULL; printf("+-----------------------------------+\n"); printf("| [SYSTEM] :: program is Started... |\n"); printf("+-----------------------------------+\n"); /* * Initialize */ /* 공유 메모리 생성 */ sShmId = shmget( KEY_ID, SIZE, IPC_CREAT | 0666 ); /* 공유 메모리 생성 실패 확인 */ STL_TRY_THROW( sShmId != -1, RAMP_ERROR_01 ); printf("공유 메모리를 생성하였습니다.\n"); /* 공유 메모리 attach */ gShmAddrStart = shmat( sShmId, (void *)0, 0 ); /* attach 실패 확인 */ STL_TRY_THROW( gShmAddrStart != (void *)-1, RAMP_ERROR_02 ); printf("공유 메모리를 attach 하였습니다.\n"); /* * attach한 shared memory 주소로 구조체를 캐스팅 * * < SHARED MEMORY > * +---------+------------------------------------------------------- * | sStruct | * +---------+------------------------------------------------------- * ^ * gShmAddrStart * */ sStruct = (qStruct *)gShmAddrStart; /* 구조체 sStruct 초기화 */ qInitialize( sStruct ); /* 각 구조체들의 크기 */ sStructSize = sizeof( qStruct ); sNodeSize = sizeof( qNode ); /* ( shared memory 주소값 ) + ( 구조체 크기 )값을 구조체 멤버에 저장 */ sStruct->mShmAddr = gShmAddrStart + sStructSize; /* * DO */ for( sRepeatCount = 0; sRepeatCount < PROCESS_COUNT; sRepeatCount++ ) { sProcessId[sRepeatCount] = fork(); if( sProcessId[sRepeatCount] > 0 ) { /* 부모 프로세스 */ /* do nothing */ } else if( sProcessId[sRepeatCount] == 0 ) { /* 자식 프로세스 */ /* 자식 프로세스 절반은 enqueue, 절반은 dequeue */ if( sRepeatCount % 2 == 0 ) { /* Enqueue */ qEnqueue( sStruct, sRepeatCount ); } else { /* Dequeue */ qDequeue( sStruct, sRepeatCount ); } exit( STL_SUCCESS ); } else { /* fork 실패 */ STL_TRY_THROW( STL_SUCCESS, RAMP_ERROR_04 ); } } /* * Finalize */ /* 부모 프로세스의 wait 호출 */ for( sRepeatCount = 0; sRepeatCount < PROCESS_COUNT; sRepeatCount++ ) { sProcessId[sRepeatCount] = wait( &sStatus ); } /* 세마포어 종료 */ sem_destroy( &sStruct->mSemaphore ); printf("세마포어를 종료하였습니다.\n"); /* 공유 메모리 detach */ sIsDetachShm = shmdt( gShmAddrStart ); /* detach 실패 확인 */ STL_TRY_THROW( sIsDetachShm != -1, RAMP_ERROR_03 ); printf("공유 메모리를 detach 하였습니다.\n"); printf("+-----------------------------------+\n"); printf("| [SYSTEM] :: program is Exited... |\n"); printf("+-----------------------------------+\n"); return STL_SUCCESS; STL_CATCH( RAMP_ERROR_01 ) { printf("[ERROR-01] :: cannot get shared memory which key '%d'.\n", KEY_ID ); } STL_CATCH( RAMP_ERROR_02 ) { printf("[ERROR-02] :: cannot attach shared memory which key '%d'.\n", KEY_ID ); } STL_CATCH( RAMP_ERROR_03 ) { printf("[ERROR-03] :: cannot detach shared memory which key '%d'.\n", KEY_ID ); } STL_CATCH( RAMP_ERROR_04 ) { printf("[ERROR-04] :: cannot create child process.\n"); } STL_FINISH; return STL_FAILURE; } void * qInitialize( qStruct * aStruct ) { aStruct->mQueue.mFrontNode = NULL; aStruct->mQueue.mRearNode = NULL; aStruct->mShmAddr = NULL; aStruct->mCount = 0; /* 세마포어 초기화 */ sem_init( &aStruct->mSemaphore, 1, 1 ); } void * qEnqueue( qStruct * aStruct, int aProcessId ) { int sRepeatCount = 0; int sNodeSize = 0; qNode * sNewNode = NULL; sNodeSize = sizeof( qNode ); /* rand() */ srand( aProcessId ); while( sRepeatCount < DATA_MAX_COUNT ) { /* semaphore lock */ sem_wait( &aStruct->mSemaphore ); if( aStruct->mCount >= PROCESS_COUNT ) { /* printf("queue is full!\n"); */ } else { /* * < SHARED MEMORY > * +---------+----------+-------------------------------------------- * | sStruct | sNewNode | * +---------+----------+-------------------------------------------- * ^ * mShmAddr * */ sNewNode = (qNode *)aStruct->mShmAddr; aStruct->mShmAddr += sNodeSize; /* 두 자리 임의의 수를 sNewNode의 mData에 저장 */ sNewNode->mData = rand()%90 + 10; sNewNode->mNextNode = NULL; if( aStruct->mCount == 0 ) { aStruct->mQueue.mFrontNode = sNewNode; sNewNode->mPrevNode = NULL; } else { aStruct->mQueue.mRearNode->mNextNode = sNewNode; sNewNode->mPrevNode = aStruct->mQueue.mRearNode; } aStruct->mQueue.mRearNode = sNewNode; aStruct->mCount++; printf("[#%3d][ENQUEUE_DATA] : %d QUEUE STATUS [ %2d/%d ]\n", aProcessId, aStruct->mQueue.mRearNode->mData, aStruct->mCount, PROCESS_COUNT ); sRepeatCount++; } /* semaphore unlock */ sem_post( &aStruct->mSemaphore ); usleep(50); } } void * qDequeue( qStruct * aStruct, int aProcessId ) { int sRepeatCount = 0; int sOutputData = 0; int sStructSize = 0; int sNodeSize = 0; void * sShmAddr = NULL; sStructSize = sizeof( qStruct ); sNodeSize = sizeof( qNode ); while( sRepeatCount < DATA_MAX_COUNT ) { sem_wait( &aStruct->mSemaphore ); if( aStruct->mCount == 0 ) { /* printf("queue is empty!\n"); */ } else { sOutputData = aStruct->mQueue.mFrontNode->mData; if( aStruct->mCount == 1 ) { aStruct->mQueue.mFrontNode = NULL; aStruct->mQueue.mRearNode = NULL; aStruct->mCount = 0; } else { aStruct->mQueue.mFrontNode = aStruct->mQueue.mFrontNode->mNextNode; aStruct->mQueue.mFrontNode->mPrevNode = NULL; aStruct->mCount--; } printf("[#%3d][DEQUEUE_DATA] : %d QUEUE STATUS [ %2d/%d ]\n", aProcessId, sOutputData, aStruct->mCount, PROCESS_COUNT ); sRepeatCount++; } sem_post( &aStruct->mSemaphore ); usleep(50); } }
공부/코딩연습 등의 이유로 얼마든지 퍼가셔도 좋습니다.
하지만 라인마다 의미를 파악하지 않고 무작정 복사 붙여넣기는
아무것도 남지 않습니다.
또한 댓글로 궁금하신 라인 등 얼마든지 물어보시면
바로바로 대답해드리겠습니다 :)
공부를 게을리하지 맙시다!
'IT > C - Programming' 카테고리의 다른 글
[C코드] :: MULTITHREAD QUEUE code (멀티 스레드를 이용한 큐 코드) (3) | 2019.05.24 |
---|---|
[C개념] :: 자료형(Data type) 별 크기 및 범위 (0) | 2018.09.28 |
[C코드] :: BINARY SEARCH code (이진 탐색 코드) (0) | 2018.03.28 |
[C코드] :: INSERTION SORT code (삽입 정렬 코드) (0) | 2018.03.27 |
[C코드] :: Array based QUEUE code (배열 기반 큐 코드) (0) | 2018.03.26 |