일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- esp32
- 힐스테이트 광교산
- 나스닥
- 티스토리챌린지
- raspberry pi
- Espressif
- 코스피
- 홈네트워크
- 배당
- 퀄컴
- Apple
- 애플
- matter
- RS-485
- 오블완
- Bestin
- homebridge
- Python
- Home Assistant
- 공모주
- 엔비디아
- 파이썬
- 현대통신
- 국내주식
- 매터
- 해외주식
- 월패드
- 미국주식
- MQTT
- ConnectedHomeIP
- Today
- Total
YOGYUI
C++::Linux에서 프로그램 중복 실행 방지 본문
C++::Prevent duplicated execution (Linux)
지난 포스팅에서 특정 프로세스의 ID값(PID)들을 조회하는 코드를 구현해봤다
C++::Linux에서 특정 프로세스의 ID값(PID) 읽어오기 (pidof 명령어)
이를 활용해 프로그램의 중복 실행을 방지할 수 있는 코드를 작성해보자
모든 코드는 Ubuntu 20.04.4 LTS 환경에서 테스트함
1. 코드 구현
#include <cstdio>
#include <vector>
#include <unistd.h>
#include <string>
#include <cstring>
#include <sstream>
#include <algorithm>
void get_process_id_list(const char *proc_name, std::vector<pid_t> &list) {
char command[256]{0, };
char result[256]{0, };
sprintf(command, "pidof %s", proc_name);
// get "pidof" result as string
FILE *fp = popen(command, "r");
list.clear();
if (fp) {
size_t ret = fread(result, 1, 256, fp);
pclose(fp);
if (ret <= 0) {
printf("failed to get pidof command result\n");
return;
}
// convert as std::string and remove new line character(\n)
std::string szres(result);
szres.replace(szres.find('\n'), 1, "");
// split string and push pid values in vector (delimeter = ' ')
std::string szpid;
std::istringstream stream(szres);
while (getline(stream, szpid, ' ')) {
pid_t pid = strtol(szpid.c_str(), nullptr, 10);
list.push_back(pid);
}
}
}
bool check_executable(const char *proc_name) {
std::vector<pid_t> pid_list;
// get pid list of specific process
get_process_id_list(proc_name, pid_list);
// get pid of current process and remove it from vector
pid_t my_pid = getpid();
pid_list.erase(std::remove(pid_list.begin(), pid_list.end(), my_pid), pid_list.end());
// check size of vector (if not empty, process is duplicated)
if (!pid_list.empty()) {
printf("Found other process which is running (count: %zu)\n", pid_list.size());
for (auto &pid : pid_list) {
printf("%d\n", pid);
}
return false;
}
return true;
}
check_executable 함수 호출 시, 특정 프로세스의 PID값들을 벡터(pid_t형)에 담은 후, 현재 실행중인 프로세스의 PID값이 존재할 경우 벡터에서 지운 뒤 벡터의 크기가 1 이상일 경우 (=not empty) 해당 프로세스가 중복 실행되었다고 판단할 수 있게 구현해봤다
※ <unistd.h>내의 getpid() 함수를 호출하면 현재 실행중인 프로세스의 PID값을 쉽게 얻을 수 있다
2. 테스트
테스트를 위해 main.cpp 스크립트를 간단하게 작성해보자
extern char *__progname;
int main(int argc, char *argv[]) {
pid_t my_pid = getpid();
if (!check_executable(__progname)) {
return 1;
} else {
while (1) {
printf("process <%s (PID %d)> is running\n", __progname, my_pid);
sleep(5);
}
}
return 0;
}
현재 실행중인 프로세스의 이름은 argv[0]를 활용하는게 일반적인데, 만약 __progname 전역변수를 사용할 수 있는 환경이라면 이를 활용하는게 훨씬 편하다 (물론 이식성은 떨어진다는게 단점이지만..)
g++로 실행 파일을 빌드해주자 (실행파일명은 test로 임의 지정)
$ g++ -g main.cpp -o test
이제 터미널 2개를 열어 각 터미널에서 프로그램을 실행해보자
최초 프로그램 실행 시 PID 134663으로 프로세스가 실행된 뒤 while문이 계속 돌게 되는데, 이 때 두번째 실행 시 다른 프로세스가 실행중이라는 메시지와 함께 프로그램이 종료된다 (while문으로 가지 않고 return)
3. Github repository
※ Windows 기반 프로그램을 Linux 환경으로 포팅하는 과정에서 이것저것 필요한 코드들을 정리해서 깃허브에 올리고 있다
https://github.com/YOGYUI/Sniffets/tree/main/linux_prevent_duplicated_execution/src
Windows OS에서는 MFC의 CreateMutex API로 간단하게 뮤텍스 기반 중복 실행 방지 구문을 만들 수 있는데(길어봐야 코드 2~3줄?), Linux는 조금은 번거롭게 구현해야만 했다
그래도 process id는 이곳 저곳에서 쓸 일이 많으니 이참에 방법을 확실히 알아냈다는데 의의를 둬야겠다
끝~!
[참고]
https://stackoverflow.com/questions/3385229/c-erase-vector-element-by-value-rather-than-by-position
'Software > C, C++' 카테고리의 다른 글
[C++] sort std::vector by multiple attributes (0) | 2023.08.18 |
---|---|
C++::Linux에서 특정 프로세스의 ID값(PID) 읽어오기 (pidof 명령어) (0) | 2022.08.22 |
C++::Linux에서 네트워크 어댑터 MAC Address 가져오기 (0) | 2022.07.27 |
C++::디렉터리 존재 여부 확인하기 (g++) (0) | 2022.07.25 |
C++::chrono - 현재 날짜/시간 가져오기 (밀리초 포함) (0) | 2022.07.24 |