728x90
반응형
개요
- multi process간에 사용할 semaphore 를 c++로 구현함.
- named semaphore를 사용
- semaphore name은 process명으로 자동 사용
Source Code
/* Copyright (C)
* 2021 - doitnowman
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
#include <stdio.h> /* printf() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <unistd.h>
#include <sys/types.h> /* key_t, sem_t, pid_t */
#include <sys/wait.h>
#include <sys/shm.h> /* shmat(), IPC_RMID */
#include <errno.h> /* errno, ECHILD */
#include <semaphore.h> /* sem_open(), sem_destroy(), sem_wait().. */
#include <fcntl.h> /* O_CREAT, O_EXEC */
#include <iostream>
#include <sstream>
#include <time.h>
#define SEMA_NAME "pSem"
class SemaPhore
{
private:
sem_t *sem = nullptr; /* synch semaphore */
unsigned int value = 1; /* semaphore value */
struct timespec tm; /* semaphore timeout */
time_t timeout; /* timeout value */
std::string sema_name;
public:
SemaPhore(time_t timeout_ = 60)
:timeout(timeout_)
{
#ifdef __WIN32__
#else
extern char* __progname;
sema_name = __progname;
#endif
if(false == CheckProcessDuplication(sema_name)) {
/* unlink prevents the semaphore existing forever */
sem_unlink(sema_name.c_str());
sem = sem_open(sema_name.c_str(), O_CREAT, 0644, value);
} else {
/* initialize semaphores for shared processes */
sem = sem_open(sema_name.c_str(), O_EXCL, 0644, value);
}
}
~SemaPhore() = default;
bool CheckProcessDuplication(std::string program)
{
FILE *fp = nullptr;
std::string pid;
char cpid[64] = {0, };
uint32_t run_cnt = 0;
std::ostringstream oss;
#ifdef __WIN32__
#else
oss << "ps -ef | grep " << program << " | grep -v grep | awk -F' ' '{print $2}'";
if (nullptr != (fp = popen(oss.str().c_str(), "r"))) {
while(fgets(cpid , 64, fp)) {
run_cnt++;
}
pclose(fp);
}
return (run_cnt >= 2);
#endif
}
bool Lock()
{
if (sem) {
/* P operation */
clock_gettime(CLOCK_REALTIME, &tm);
tm.tv_sec += timeout;
if (!sem_timedwait(sem, &tm)) {
return true;
}
}
return false;
}
bool Unlock()
{
if (sem) {
/* V operation */
if (!sem_post(sem)) {
return true;
}
}
return false;
}
};
int main(int argc, char* argv[])
{
SemaPhore sema;
while(1) {
if (true == sema.Lock()) {
std::cout << " in critical section" << std::endl;
sleep (5);
sema.Unlock();
}
std::cout << " after critical section" << std::endl;
sleep (1);
}
}
CMakeLists.txt
#cmake 최소 버전
cmake_minimum_required(VERSION 3.10.1)
#프로젝트 이름
project(semaphore)
#CMake 옵션 처리
set(CMAKE_VERBOSE_MAKEFILE ON)
#컴파일 옵션 추가
add_compile_options(-std=c++11 -ggdb3 -O3 -Wall)
#-Werror)
#define 추가
add_definitions(-D_REENTRANT)
#header include 경로
include_directories()
#라이브러리 링크 디렉토리 경로
link_directories()
#전체 적용될 라이브러리 링크
link_libraries(
rt
pthread
)
#cmake 변수 처리
file(GLOB main_src "./semaphore.cpp")
#라이브러리 생성
#set(OUTPUT_STATIC_LIB "hello")
#add_library(${OUTPUT_STATIC_LIB} STATIC ${all_srcs})
#실행 파일 생성
add_executable(sema ${main_src})
#특정 실행 파일에 적용될 라이브러리 링크추가
#target_link_libraries(server
# -Wl,--disable-new-dtags
# -Wl,--rpath,/home/openssl
#)
#실행 파일 생성
#add_executable(client ${client_src})
#target_link_libraries(client
# -Wl,--disable-new-dtags
# -Wl,--rpath,/home/openssl
#)
728x90
반응형
'프로그래밍 > ExampleCode.com' 카테고리의 다른 글
[IPC] shared memory 예제 코드 (5) | 2018.09.20 |
---|---|
[IPC] pipe 예제 코드 (0) | 2018.09.20 |
[IPC] named pipe 예제 코드 (0) | 2018.09.20 |
[IPC] message queue 예제 코드 (0) | 2018.09.20 |
[IPC] 메모리 맵 mmap() 예제 코드 (0) | 2018.09.20 |