프로세스 중복 방지

gyubong park·2022년 3월 30일
0

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

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

관련 채용 정보