EXECVE(2)

이름
execve - 프로그램을 실행한다.

사용법
#include <unistd.h>

int execve (const char *filename, char *const argv [], char *const envp[]);

설명
execve()는 filename이 가리키는 파일을 실행한다. filename은 바이너리 실행 파일이거나 "#! interpreter [arg]"와 같은 라인으로 시작하는 스크립트 파일이어야 한다. 후자의 경우, interpreter는 interpreter [arg] filename와 같은 형태로 수행이 가능한 (스크립트가 아닌) 바이너리 실행 파일이어야 한다. argv는 새로이 실행할 프로그램에 전달하는 인수 문자열의 배열이다. envp는 보통 key=value과 같은 형태의 문자열 배열이며 환경 변수를 설정해놓은 것처럼 전달된다. argv와 envp는 모두 NULL 포인터로 끝나야만 한다. 실행할 프로그램을 int main(int argc, char *argv[], char *envp[])와 같이 정의하면 인수 문자열 배열과 환경 변수를 main () 함수에서 사용할 수 있게 된다. execve()가 성공할 경우 반환하지 않는다. 그리고 호출된 프로세스는 호출한 프로세스의 텍스트, 데이타, bss와 스택을 덮어쓴다. 그리고 호출된 프로세스는 호출한 프로세스의 PID와 exec 시 닫히게 설정되지 않은 모든 열린 파일 디스크립터들을 상속받는다. 호출한 프로세스에 대기중이던 모든 시그널도 클리어되고 호출한 프로세스가 처리하도록 설정되어 있던 시그널들도 원래 상태로 되돌아간다. 호출한 프로그램을 ptrace(2) 로 추적하고 있었다면 execve()가 성공한 후 SIGTRAP이 전달된다. 만약 filename가 가리키는 실행 파일의 set-uid 비트가 설정되어 있다면 호출한 프로세스의 실질적인 사용자 ID(uid)는 실행 파일의 소유자로 바뀐다. 유사하게, 실행 파일의 set-gid 비트가 설정되어 있다면 호출한 프로세스의 실질적인 그룹 ID(gid)도 실행 파일의 그룹으로 바뀐다. 만약 실행 파일이 동적 라이브러리와 링크되고 공유 라이브러리 stub을 포함하는 a.out 형식이라면 프로그램 수행 전에 리눅스의 동적 링커인 ld.so(8) 가 동작한다. 만약 실행 파일이 동적 라이브러리와 링크되는 ELF 형식이라면 PT_INTERP 세그먼트가 가리키는 이름의 인터프리터가 공유 라이브러리를 로드하기 위해 동작할 것이다. 그 인터프리터는 보통 리눅스 libc 버전 5의 경우 /lib/ld-linux.so.1이며, GNU libc 버전 2의 경우 보통 /lib/ld-linux.so.2이다.

반환값
성공시, execve()는 반환되지 않고, 에러시 -1이 반환되고, errno 는 적절히 설정된다.

에러

EACCES
    파일이나 스크립트 인터프리터가 정규 파일이 아니다.

EACCES
    파일이나 스크립트 혹은 ELF 인터프리터에 실행 권한이 없다.

EACCES
    파일 시스템이 noexec 설정으로 마운트되었다.

EPERM
    파일 시스템이 nosuid 설정으로 마운트되어 있으며, 사용자가 슈퍼유저가 아니고 파일이 SUID나 SGID 비트가 설정되어 있지 않다.

EPERM
    프로세스가 추적(trace)되고 있으며, 사용자가 슈퍼유저가 아니고 파일이 SUID나 SGID 비트가 설정되어 있다.

E2BIG
    인수 리스트가 너무 크다.

ENOEXEC
    실행 파일이 알아 볼수 없는 형식이다. 다른 플랫폼용의 파일이거나 형식상의 에러를 지니고 있어 실행할 수 없다.

EFAULT
    filename 이 접근할 수 없는 주소 영역을 가리킨다.

ENAMETOOLONG
    filename 이 너무 길다.

ENOENT
    filename 혹은 스크립트나 ELF 인터프리터가 존재하지 않거나 실행시 필요로 하는 공유 라이브러리를 찾지 못했다.

ENOMEM
    커널 메모리가 충분치 않다.

ENOTDIR
    filename 혹은 스크립트나 ELF 인터프리터의 경로명의 앞부분 경로명(prefix)이 디렉토리가 아니다.

EACCES
    filename 혹은 스크립트나 ELF 인터프리터의 경로명의 앞부분 경로명이 가리키는 디렉토리를 검색할 권한이 없다.

ELOOP
    filename 혹은 스크립트나 ELF 인터프리어터의 경로명을 따라가는 과정에 너무 많은 심볼릭 링크가 발견되었다.

ETXTBSY
    다른 하나 이상의 프로세스가 실행 파일에 쓰기 위해 열어놓았다.

EIO I/O 에러가 발생하였다.

ENFILE
    시스템에서 생성할 수 있는 최대 파일 개수에 도달하였다.

EMFILE
    프로세스가 열 수 있는 최대 파일 개수에 도달하였다.

EINVAL
    ELF 실행 파일이 하나 이상의 PT_INTERP 세그먼트를 가지고 있다. (즉 ELF 인터프리터를 하나 이상 가리키고 있다.)

EISDIR
    가리키는 ELF 인터프리터가 디렉토리다.

ELIBBAD
    ELF 인터프리터가 알 수 없는 형식이다.

호환
SVr4, SVID, X/OPEN, BSD 4.3. POSIX은 #!실행을 문서화 하지않았지만, 그 외에는 호환성이 있다. SVr4는 추가적인 에러상태 EAGAIN, EINTR, ELIBACC, ENOLINK, EMULTIHOP를 문서화했다; POSIX은 ETXTBSY, EPERM, EFAULT, ELOOP, EIO, ENFILE, EMFILE, EINVAL, EISDIR ,ELIBBAD 에러상태를 문서화하지 않았다.

주의
SUID와 SGID 프로세스들은 ptrace()되지 않는다. 리눅스는 스크립트의 SUID와 SGID 비트는 무시한다. 파일 시스템을 nosuid 설정으로 마운트했을 때의 결과는 리눅스 버전마다 다르다: 어떤 버전의 리눅스에서는 SUID/SGID 실행 파일을 실행했을 때 사용자에게 없던 권한이 생기는 경우 실행을 거부하고 EPERM 에러를 반환한다. 다른 버전의 리눅스에서는 그냥 SUID/SGID 비트를 무시하고 성공적으로 수행할 것이다. #! 로 시작하는 스크립트의 첫 라인의 최대 크기는 127 byte이다.

관련 항목
chmod(2), fork(2), execl(3), environ(5), ld.so(8)

역자
ASPLINUX<man@asp-linux.co.kr>, 2000년 7월 29일
한글 Manpage 프로젝트 (http://man.kldp.org) 2004년 3월 23일