내가 만든 프로그램을 하나의 컴퓨터당 하나의 프로세스만 동작하려면 어떻게 해야할까? 동일한 프로세스를 중복으로 실행시키는 것을 방지해보자
개발 중에 '하나의 프로세스만 동작하게 해주세요'라는 요청이 있었다. 그래서 나는 인터넷 검색을 해보았고 stack-overflow에 좋은 방법을 찾아냈다.
해당 방법은 파일락을 이용해서 최초의 프로세스 생성시 생성된 파일을 lock하여 후에 동일한 프로세스가 실행되더라도 이를 방지하는 방법이다.
stack-overflow 찾은 방법을 예제로 만들어보았다.
#include <iostream>
#include <sys/file.h>
#include <unistd.h>
#include <string>
using namespace std;
int lockFile(const std::string& fileName){
int pid_file = open(fileName.c_str(), O_CREAT | O_RDWR, 0666); // 0666 : file
// LOCK_SH 공유 잠금
// LOCK_EX 배타(exclusive)잠금
// LOCK_UN 잠금을 품
// LOCK_NB 잠금일 때 블럭하지 않고 리턴
return flock(pid_file, LOCK_EX | LOCK_NB);
}
bool isFileLock(const std::string& fileName){
int rc = lockFile(fileName);
if(rc) {
if(EWOULDBLOCK == errno){
// 만약 파일이 잠겨있게 되면 errno에 EWOULBLOCK가 설정
cout << "file is locked" << endl;
return true;
}
}
cout << "file is not locked" << endl;
return false;
}
void updatePidFile(const std::string& fileName){
FILE* file = fopen(fileName.c_str(), "w+"); // 무조건 새로 만들기
if(file){
std::cout << "file open" << std::endl;
string str_pid = std::to_string(getpid());
fwrite(str_pid.c_str(), 1, str_pid.size(), file);
fflush(file);
}else{
std::cout << "can not open file " << std::endl;
exit(EXIT_FAILURE);
}
fclose(file);
}
int main() {
// pid를 담는 파일 생성
std::string fileName = "/home/bong/Desktop/work/anyapi/only_one_process.pid";
if(access(fileName.c_str(), F_OK))
{
cout << "file is not exist" << endl;
// 파일 생성
updatePidFile(fileName);
lockFile(fileName);
}else{
cout << "file is already exist" << endl;
if(isFileLock(fileName)){ // 파일이 lock을 잡고 있는지 확인
std::cout << "current Process is running [" << getpid() << "]" << std::endl;
std::cout << "another process already running" << std::endl;
exit(EXIT_FAILURE);
}else{
updatePidFile(fileName);
lockFile(fileName);
}
}
// this is the first instance
std::cout << "Process is running [" << getpid() << "]" << std::endl;
sleep(120);
return 0;
}