본문 바로가기
Raspberry Pi (Linux, ubuntu)

라즈베리파이 프로그램 1개만 실행시키기 (먼저 실행된 프로그램 종료하기)

by 소나무기운 2023. 5. 20.
반응형

[2023/05/20] First Start.

소나무 기운 ,  전자제품 개발/생산

라즈베리파이 프로그램 1개만 실행시키기 (먼저 실행된 프로그램 종료하기)

라즈베리파이에서 프로그램 진행 중 하드웨어를 점유하는 프로그램 ( 시리얼 포트, 랜 포트)은 1개만 실행되어야 문제가 없는 경우가 있습니다. 같은 COMM번호를 사용하거 같은 port를 이용할때 문제가 생긱 수 있죠.

또 특이한 경우는 새로 시작된 프로그램은 실행을 시키고 이전에 실행된 프로그램을 종료하고자 하는 상황이 생겼습니다.

이와 같은 작업이 가능하도록 프로그램을 처리 하였습니다.

 

 

기본 개념

시스템 명령어 중에 pgrep라는 명령이 있습니다.

현재의 프로세스의 PID값을 가져오게 됩니다.


pgrep는 지정된 이름을 가진 프로세스의 PID(Process ID)를 검색하는 명령어입니다. 주어진 이름에 해당하는 모든 프로세스의 PID를 반환합니다.

pgrep 명령어를 사용할 때 다양한 옵션을 제공하여 검색을 세부적으로 조정할 수 있습니다. 주요 옵션은 다음과 같습니다:

-a 또는 --list-full: 프로세스 이름과 함께 PID를 출력합니다.
-l 또는 --list-name: 프로세스 이름만 출력합니다.
-f 또는 --full: 프로세스의 전체 명령어를 포함하여 검색합니다.
-i 또는 --ignore-case: 대소문자를 구분하지 않고 검색합니다.
-n 또는 --newest: 가장 최근에 실행된 프로세스의 PID만 출력합니다.
-o 또는 --oldest: 가장 오래된 프로세스의 PID만 출력합니다.
-x 또는 --exact: 정확히 주어진 이름과 일치하는 프로세스만 검색합니다.

예를 들어, "myprogram"이라는 이름을 가진 최근에 실행된 프로세스의 PID를 검색하려면 다음과 같이 사용할 수 있습니다:

 

pgrep -n myprogram

bash라는 프로세스가 몇 개나 실행되고 있는지 확인합니다.

보시는것 처럼 다섯개가 보입니다.

기본적으로는 PID의 오름차순으로 정렬되어 보여집니다.

 

몇 가지 옵션이 있습니다. 그중 두가지를 사용합니다.

-o , -x 입니다.

 

-o 옵션으로 오래된 프로세스의 PID를 하나 가져옵니다.

가져오 PID를 사용하여 프로세스를 kill해 줍니다.

 

 

 

 

구현 방법

전체 프로그램 내용입니다. 프로그램 시작 시 terminateEarliestMyprogramProcess()를 호출하여 이전에 이미 실행되고 있는 Myprogram이 있으면 그 프로세스를 종료합니다.

 

//=============================================================================
void terminateEarliestMyprogramProcess()
{
    const char *processName = "RS2021";
    char command[100];
    char pid[10];
    int earliestPid = -1;
    FILE *fp;

    // Find the PIDs of all RS2021 processes
    snprintf(command, sizeof(command), "pgrep -o -x %s", processName);
    fp = popen(command, "r");
    if (fp != NULL)
        if (fgets(pid, sizeof(pid), fp) != NULL)
        {
            earliestPid = atoi(pid);
        }

    pclose(fp);

    if (earliestPid != -1)
    {
        // Terminate the earliest RS2021 process
        snprintf(command, sizeof(command), "kill %d", earliestPid);
        printf("Terminated RS2021 process with PID: %d\n", earliestPid);
        system(command);
    }
    else
    {
        printf("No RS2021 processes are currently running.\n");
    }
}

//=============================================================================

int main(void)
{
	terminateEarliestMyprogramProcess();
    
    // my program
    while(1)
    {
    }
}

//=============================================================================

 

-o 대신 -n을 넣으면 이전에 실행된 프로그램을 두 지금 실행된 내 프로그램을 종료하게 됩니다.

 

마무리

터미널에서 이용하는 명령어들을 이용하여 프로그램 중복 실행 방지 방법을 알아보았습니다.

이 방법 이외에도 여러가지 방법이 있습니다. 다만 대부분 새로 시작되는 프로그램을 시작하지 않도록 하는 방법이 대부분입니다.

하지만 이번 소개한 방법은 새로 시작되는 프로그램이나 이전 시작된 프로그램 중 어떤것을 실행할지 선택할 수 있어 좋은 방법이라 보여집니다.

 

리눅스에서 프로그램 중복 실행을 방지하는 몇 가지 방법은 다음과 같습니다:

PID 파일 사용: 프로그램이 실행될 때 PID 파일을 생성하고, 다음 실행 시 해당 PID 파일이 존재하는지 확인하여 중복 실행을 방지합니다.

파일 락(Lock) 사용: 프로그램이 실행되는 동안 특정 파일을 락하여 다른 인스턴스의 실행을 막습니다. 파일 락은 fcntl 또는 flock 함수를 사용하여 구현할 수 있습니다.

IPC(Inter-Process Communication) 기법 사용: 프로그램 간 통신을 통해 중복 실행 여부를 확인합니다. 예를 들어, 시스템 전역에 공유 메모리, 세마포어, 메시지 큐 등을 사용하여 중복 실행을 방지할 수 있습니다.

네트워크 포트 사용: 프로그램이 특정 포트를 점유하여 다른 인스턴스의 실행을 막습니다. 다른 인스턴스가 해당 포트를 사용 중인지 확인하여 중복 실행을 방지합니다.

pgrep 또는 pidof 명령어 사용: pgrep 또는 pidof 명령어를 사용하여 실행 중인 프로세스의 PID를 검색하고, 중복되는 PID가 있는지 확인하여 중복 실행을 방지할 수 있습니다.

파일 시스템 락(Lock) 사용: 특정 파일을 락하여 다른 프로세스의 접근을 막아 중복 실행을 방지할 수 있습니다. 예를 들어, flock 함수를 사용하여 파일 락을 구현할 수 있습니다.

환경 변수 사용: 실행 중인 프로세스에서 특정 환경 변수를 설정하고, 다른 인스턴스가 실행되려고 할 때 해당 환경 변수를 체크하여 중복 실행을 방지할 수 있습니다.

이러한 방법들은 중복 실행을 방지하기 위한 일반적인 접근 방식입니다. 실제 구현은 상황과 요구 사항에 따라 달라질 수 있으며, 자세한 내용은 해당 방법들을 선택한 후 관련 문서나 예제를 참고하는 것이 좋습니다.

 

 

 

 

 

참고문헌

 

 

 

 
 

 

 

틀린 부분이나 질문은 댓글 달아주세요.

즐거운 하루 보내세요. 감사합니다.

 

 

반응형

댓글