프로세스 중복 방지

gyubong park·2022년 3월 30일

내가 만든 프로그램을 하나의 컴퓨터당 하나의 프로세스만 동작하려면 어떻게 해야할까? 동일한 프로세스를 중복으로 실행시키는 것을 방지해보자

개발 중에 '하나의 프로세스만 동작하게 해주세요'라는 요청이 있었다. 그래서 나는 인터넷 검색을 해보았고 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;
}
profile
초보 개발자

0개의 댓글