YOGYUI

C++::Linux에서 특정 프로세스의 ID값(PID) 읽어오기 (pidof 명령어) 본문

Software/C, C++

C++::Linux에서 특정 프로세스의 ID값(PID) 읽어오기 (pidof 명령어)

요겨 2022. 8. 22. 23:16
반응형

C++::Get PID of specific process using 'pidof' command (Linux)

리눅스에서 특정 프로세스의 ID(PID)값을 읽어오는 C++코드를 작성해봤다

모든 코드는 Ubuntu 20.04.4 LTS 환경에서 테스트함

1. 터미널 명령어 (pidof)

리눅스에서 pidof 명령어를 프로세스명과 함께 터미널에 입력하면 해당 이름을 가진 프로세스(들)의 ID값을 조회할 수 있다 (예를 위해 VSCode를 여러개 실행시킨 후 System Monitor 툴과 비교해봤다)

$ pidof <프로세스명>

VSCode의 프로세스명은 code

터미널 명령어 실행 결과
System Monitor 툴

이 외에도 ps, pgrep 등 다른 명령어를 통해서도 같은 결과를 얻을 수 있으니, 따로 검색해보기 바란다

2. 코드 구현

C/C++에서는 popen 함수로 코드상에서 쉘에 파이프(pipe)를 생성한 뒤 터미널 명령어를 호출하고 결과값을 문자열로 받아볼 수 있다

main.cpp 파일에 다음과 같이 테스트 코드를 작성해보자

#include <cstdio>
#include <unistd.h>
#include <cstring>

void get_process_id_list(const char *proc_name) {
    char command[256]{0, };
    char result[256]{0, };

    sprintf(command, "pidof %s", proc_name);
    // get "pidof" result as string
    FILE *fp = popen(command, "r");
    if (fp) {
        size_t ret = fread(result, 1, 256, fp);
        pclose(fp);
        if (ret <= 0) {
            printf("failed to get pidof command result\n");
            return;
        }
        printf("pidof result: %s", result);
    }
}

int main(int argc, char *argv[]) {
    if (argv[1]) {
        get_process_id_list(argv[1]);
    }

    return 0;
}

main 함수에서는 인자로 프로세스명을 받을 수 있도록 구현했다

g++로 바이너리 실행 파일을 생성해주자

$ g++ -g main.cpp -o get_pid_list

실행 파일을 터미널에서 호출해서 VSCode 프로세스의 PID 값들을 출력해보자

$ ./get_pid_list code

파일 실행 결과
System Monitor 결과

 

3. 벡터(std::vector)에 PID값 저장

앞서 pidof 명령어를 popen으로 invoke하여 결과를 문자열로 받아봤다

좀 더 고급지게(?) PID값들이 나열된 문자열은 공백(space)로 분리되어있는데, 각 PID값들을 정수값으로 변환하여 vector에 담아보자

pid_t 자료형은 int 자료형이다

#include <cstdio>
#include <vector>
#include <unistd.h>
#include <string>
#include <cstring>
#include <sstream>

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);
        }
    }
}

int main(int argc, char *argv[]) {
    std::vector<pid_t> pid_list;
    if (argv[1]) {
        get_process_id_list(argv[1], pid_list);
        printf("Process <%s> Count: %zu\n", argv[1], pid_list.size());
        for (auto & pid : pid_list) {
            printf("%d\n", pid);
        }
    }

    return 0;
}

마찬가지로 VSCode의 PID값들을 가져와보자

vectorize 코드 실행 결과

4. Github Repository

※ Windows 기반 프로그램을 Linux 환경으로 포팅하는 과정에서 이것저것 필요한 코드들을 정리해서 깃허브에 올리고 있다

https://github.com/YOGYUI/Sniffets/tree/main/linux_get_pid

 

GitHub - YOGYUI/Sniffets: 간단한 예제 코드들

간단한 예제 코드들. Contribute to YOGYUI/Sniffets development by creating an account on GitHub.

github.com

 

특정 프로세스의 PID값들을 정수값으로 변환한 뒤 벡터(배열)에 담는 방법에 대해 알아보았다

이 방법을 활용하면 프로그램의 중복 실행을 방지할 수 있는데, 이에 대해서는 다음 포스팅에서 다뤄보도록 하겠다

끝~!

 

[참고]

https://www.networkworld.com/article/3600281/using-pidof-and-pgrep-to-list-process-ids.html

https://man7.org/linux/man-pages/man3/pclose.3.html

반응형