execv(3)

#include <unistd.h>

int execv(const char *path, char *const argv[]);

execve(2)함수의 wrapping함수로 execve(path, argv, environ)을 호출한 것과 같습니다.  environ은 환경변수를 저장하고 있는 전역변수로 상위에 extern char **environ;을 선언하고 사용하면 됩니다. 실행가능한 파일인 path의 실행코드를 현재 프로세스에 적재하여 기존의 실행코드와 교체하여 새로운 기능으로 실행합니다.  즉, 현재 실행되는 프로그램의 기능은 없어지고 path 프로그램을 메모리에 loading하여 처음부터 실행합니다.

 

path는 절대 path 또는 상대 path로 표현해야 하며, 환경변수 PATH에 설정된 directory에 있는 프로그램이라도 directory까지 포함해야 실행이 됩니다.

 

환경변수는 현재 프로세스의 환경변수를 그대로 상속받습니다.

 

상세내용은 execve(2)를 참조하세요.

 

 

파라미터

path
    - 교체할 실행 파일 / 명령어.
    - path은 실행가능한 binary이거나 shell이어야 합니다.
    - path은 $PATH가 설정되어 있는 디렉토리라고 하더라도 절대 path나 
      상대 path로 정확한 위치를 지정해야 합니다.
argv
    - c언어의 main(int argc, char *argv[])에서 argv와 비슷하며, main함수에는 argc가 있지만 
      execv에는 argc가 없으므로 main의 argv에 마지막 array 다음에 NULL을 하나 더 넣어야 합니다.

 

RETURN

없음
    - 정상적으로 처리되면 execv(3) 다음 로직은 실행할 수 없습니다. 
      왜냐하면 이미 다른 프로그램이 되었기 때문입니다.


-1
    - binary 교체가 실패하였으며, 상세한 오류 내용은 errno 전역변수에 설정됩니다.

 E2BIG : argv 또는 envp list가 너무 많습니다.
 EACCES : path의 디렉토리에 구성에 search권한이 없거나 
             path 파일이 실행권한이 없거나 파일이 실행할 수 없는 파일입니다.
             또는 파일 시스템이 마운트되지 않았습니다.
 EFAULT : path이라는 변수가 access할 수 없는 메모리 영역입니다.
 EINVAL : ELF 실행파일이 하나이상의 PT_INTERP segment를 가진 경우
 EIO : I/O 오류가 발생하였습니다.
 EISDIR : path이 디렉토리입니다.
 ELIBBAD : ELF가 인식할 수 없는 format입니다.
 ELOOP : 너무 많은 symbolic link depth입니다.
 EMFILE : 프로세스가 열 수 있는 최대 갯수의 file을 open하였습니다.
 ENAMETOOLONG : path의 문자열의 파일명이 너무 길거나 디렉토리가 너무 깁니다.
 ENFILE : 시스템에서 열 수 있는 최대 갯수의 파일이 열렸습니다.
 ENOENT : path이 존재하지 않는 파일입니다.
 ENOEXEC : path이 실행할 수 없는 format입니다.
 ENOMEM : kernel이 사용할 수 있는 메모리가 부족합니다.
 ENOTDIR : path을 구성하는 디렉토리가 디렉토리가 아닙니다.
 EPERM : 파일시스템이 nosuid로 마운트되었으며, user가 superuser가 아니고 
             path이 set-user-ID, set-group-ID bit가 설정안됨
 ETXTBSY : 다른 프로세스에 의해서 쓰기를 위해 open된 경우

 


활용 예제

 

Sample. sample1.c : ls 명령어로 치환

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

int main(int argc, char *argv[])
{
    char **new_argv;
    char command[]  = "ls";
    int  idx;

    new_argv = (char **)malloc(sizeof(char *) * (argc + 1));

    /* 명령어를 ls로 변경 */
    new_argv[0] = command;

    /* command line으로 넘어온 parameter를 그대로 사용 */
    for(idx = 1; idx < argc; idx++) {
        new_argv[idx] = argv[idx];
    }

    /* argc를 execve 파라미터에 전달할 수 없기 때문에 NULL이 파라미터의 끝을 의미함 */
    new_argv[argc] = NULL;

    if(execv("/usr/bin/ls", new_argv) == -1) {
        fprintf(stderr, "프로그램 실행 error: %s\n", strerror(errno));
        return 1;
    }

    /* ls 명령어 binary로 실행로직이 교체되었으므로 이후의 로직은 절대 실행되지 않습니다. */
    printf("이곳이 이제 ls 명령어라 이 라인은 출력이 되지 않습니다.\n");

    return 0;
}

--------------------------------------------------------------

실행방법
sample1 -al <enter>
결과는 ls -al 한 것과 같음.

 


see also: Process 관리 함수 

 

 

 

블로그 이미지

사용자 자연&사람

행복한 개발자 programmer since 1995.

댓글을 달아 주세요