Exec함수란?

    이전 글(https://shyeon.tistory.com/51)에서 fork, vfork를 이용하여 자식 프로세스를 생성하여 다중 프로세스를 이용하는 프로그램을 만드는 법을 알아보았다. vfork를 이용할 경우 부모 프로세스는 자식 프로세스를 기다리는 것을 보장하고 주로 exec 계열 함수를 호출할 경우 사용한다고 했다. 그렇다면 exec 계열 함수는 어떤 기능을 수행할까?

 

    exec 계열 함수는 현재 실행되고 있는 프로세스를 다른 프로세스로 대신하여 새로운 프로세스를 실행하는 함수이다. 즉 다른 프로세스로 대체되어 주어진 경로에 있는 새로운 프로세스의 main함수부터 다시 시작된다. 

 

함수

int execl(const char *pathname, const char *arg0, ... /* (char *)0*/);
int execv(const char *pathname, char *const argv[]);
int execle(const char *pathname, const char *arg0, .../*(char *)0, char *const envp[] */);
int execve(const char *pathname,  char *const argv[], char *const envp[]);
int execlp(const char *filename, const c har *arg0, .../* (char *)0 */);
int execvp(const char *filename, char *const argv[]);

6개의 함수들이 전부 비슷하게 생겼다. 하지만 규칙을 찾을 수 있다.

  1. 뒤에 l 이 붙은 경우 : 매개변수의 인자가 list 형태이다. 즉 char*형을 나열한다.
  2. 뒤에 v가 붙은 경우 : 매개변수의 인자가 vector 형태이다. 두 번째 인잘르 보면 2차원 배열로 char*형을 배열로 한 번에 넘긴다.
  3. 뒤에 e가 붙은 경우 : 환경변수를 포함하여 넘긴다. 
  4. 뒤에 p가 붙은 경우 : 경로 정보가 없는 실행 파일 이름이다. 만약 filename에 ' / '(슬래시)가 포함되어 있으면 filename을 경로로 취급하고 슬래시가 없으면 path로 취급한다.

list 형태와 vector 형태로 넘기는 매개변수의 맨 마지막은 NULL pointer가 존재해야한다.

위 함수중 execve() 함수만 커널에서 제공하는 system call 함수이고 나머지는 라이브러리 함수이다.

 

exec 계열 함수를 호출한 프로세스에서 대체되는 프로세스로 상속되는 특징

  • 프로세스 ID와 부모 프로세스 ID
  • 실제 사용자 ID와 실제 그룹 ID
  • 추가 그룹 ID
  • 프로세스 그룹 ID
  • 세션 ID
  • 제어 터미널
  • alarm 발동까지 남은 시간
  • 현재 작업 디렉토리
  • 파일 생성 마스크
  • 파일 자물쇠들
  • 프로세스 시그널 마스크
  • 아직 처리되지 않은 시그널
  • 자원 한계
  • tms_utime, tms_stime, tms_cutime, tms_cstime

 

예제

이번 예제는 두개의 프로그램을 짜서 하나의 프로그램에서 exec함수를 실행하여 다른 프로그램으로 대체하는 프로그램을 짜보겠다.

 

1. exec1.c(exec을 호출하여 exec2를 실행하는 프로그램)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
	pid_t pid;

	if((pid = fork()) == 0) { //자식이 실행
		char *args[] = {"hello", "my", "name", "is", "shyeon", NULL}; //exec호출시 넘길 인자들
		if(execv("./exec2", args) < 0) { //exec2를 실행한다.
			fprintf(stderr, "execv error\n");
			exit(1);
		}
	}
	if(wait(NULL) == pid) { //자식이 종료되길 기다림
		printf("\nchild process exited\n");
	}
	else { //에러시 에러문구 출력
		fprintf(stderr, "wait error\n");
		exit(1);
	}

	exit(0);
}

 

2. exec2.c(exec1으로부터 실행되는 프로그램)

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv) {

	printf("parent says : ");

	for(int i = 1; i < argc; i++) { //부모에서 넘긴 인자를 출력
		printf("%s ", argv[i]);
	}

	exit(0);
}

이렇게 exec1에서 exec2로 대체한 것처럼 하나의 프로그램에서 다른 프로그램을 호출하며 프로그램을 대체할 수 있다.

 

실행 결과

위 프로그램에 대한 실행 결과이다.

exec1을 실행해서 execv를 통해 exec2가 실행되는 것을 알 수 있다.

+ Recent posts