C++에서 fork와 exec를 사용해 명령 실행하기
C++에서 시스템 명령어를 실행할 때 system() 함수를 사용할 수 있습니다. 하지만 exec 계열 함수를 사용하는 것이 더 효율적이고 안전할 수 있습니다. 다만 exec 함수는 호출된 프로세스를 대체하는 방식으로 작동하기 때문에, 기존 프로세스가 종료되지 않고 명령을 순차적으로 실행하려면 fork()와 함께 사용해야 합니다. 이번 포스팅에서는 fork()와 exec()를 사용하여 시스템 명령어를 실행하는 방법을 알아보겠습니다.
fork와 exec의 기본 개념
exec 함수
exec() 함수는 현재 프로세스를 새로운 프로그램으로 대체합니다. 이 함수가 호출되면 기존의 프로세스는 종료되고, exec로 호출된 프로그램이 그 자리를 차지합니다. 따라서 exec() 함수 이후에 실행될 코드가 존재하지 않게 됩니다. 바로 이 점이 exec 함수의 핵심적인 특징입니다.
fork 함수
fork() 함수는 현재 프로세스를 복제합니다. 부모 프로세스는 그대로 남고, 자식 프로세스가 새로 생성됩니다. 자식 프로세스에서는 새로운 작업을 실행할 수 있고, 부모 프로세스는 그 결과를 기다리는 식으로 병렬 처리를 할 수 있습니다. 자식 프로세스에서 exec() 함수를 호출하여 명령을 실행한 뒤 자식 프로세스를 종료시키는 방식으로 사용할 수 있습니다.
fork와 exec를 함께 사용하여 명령 실행
fork()와 exec()를 함께 사용하여 시스템 명령어를 실행하고, 부모 프로세스가 종료되지 않도록 하는 가장 간소화된 코드를 살펴보겠습니다.
코드 예시
#include <iostream>
#include <vector>
#include <sys/wait.h>
#include <unistd.h>
void execute_commands(const std::vector<std::string>& commands) {
std::string combined_commands;
// 명령을 &&로 연결하여 한 번에 실행
for (const auto& command : commands) {
combined_commands += command + " && ";
}
combined_commands = combined_commands.substr(0, combined_commands.size() - 4); // 마지막 && 제거
pid_t pid = fork(); // 자식 프로세스 생성
if (pid == 0) {
// 자식 프로세스에서 명령어 실행
execl("/bin/sh", "sh", "-c", combined_commands.c_str(), nullptr);
// exec 호출 실패 시
std::cerr << "Failed to execute commands" << std::endl;
_exit(1); // 자식 프로세스에서 오류 발생 시 종료
} else {
// 부모 프로세스는 자식 프로세스가 끝날 때까지 대기
waitpid(pid, nullptr, 0);
}
}
주요 동작
- 명령어 연결: 여러 명령어를
&&로 연결하여 한 번에 실행할 수 있는 하나의 문자열로 만듭니다.&&는 앞선 명령어가 성공해야 다음 명령어가 실행된다는 의미를 가집니다. fork()호출: 자식 프로세스를 생성합니다. 자식 프로세스는 부모 프로세스를 그대로 유지한 상태에서 새로운 프로세스로 작업을 처리할 수 있게 해 줍니다.- 자식 프로세스에서
exec()호출: 자식 프로세스에서exec()함수를 호출하여 쉘에서 명령어를 실행합니다. 이 때,execl()함수는/bin/sh를 사용하여 명령어를 실행하고, 부모 프로세스는 여전히 유지됩니다. - 부모 프로세스에서 대기: 부모 프로세스는 자식 프로세스가 명령어 실행을 완료할 때까지
waitpid()를 통해 대기합니다.
실행 예시
execute_commands 함수는 명령어들을 벡터 형태로 받아 순차적으로 실행합니다. 예를 들어, 다음과 같은 명령어를 실행할 수 있습니다:
int main() {
std::vector<std::string> commands = {"ls", "pwd", "date"};
execute_commands(commands);
return 0;
}
위 코드를 실행하면, ls로 디렉토리 목록을 출력한 뒤 pwd로 현재 경로를 출력하고, 마지막으로 date 명령어로 현재 날짜를 출력하게 됩니다. 이 모든 명령어는 순차적으로 실행됩니다.
마무리
이번 포스팅에서는 fork()와 exec()를 사용하여 시스템 명령어를 실행하는 방법에 대해 설명했습니다. fork()를 통해 자식 프로세스를 생성한 후, exec()로 명령어를 실행하면 부모 프로세스는 그대로 유지되면서 자식 프로세스에서 명령어를 처리할 수 있습니다.
이 구조는 시스템 명령어를 효율적으로 실행하면서 기존 프로세스의 흐름을 유지할 수 있게 해 주는 중요한 방법 중 하나입니다. 간단하면서도 강력한 이 방법을 통해 C++에서 더욱 다양한 시스템 작업을 수행할 수 있습니다.
'MFC(Window Programming)' 카테고리의 다른 글
| [linux] ffmpeg mp4 player Continuous (0) | 2024.10.23 |
|---|---|
| [linux]ffmpeg mp4 player (0) | 2024.10.23 |
| Mutex, Semaphore, Critical Section 동기화 메커니즘 성능 비교 (0) | 2024.09.27 |
| ifstream, ostream, stringstream, std::getline (1) | 2024.09.25 |
| C++ 정규식과 Raw String Literal: 매칭과 사용법 (1) | 2024.09.24 |