ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • C/C++ execl(3), execv(3), execle(3), execve(2), execlp(3), execvp(3)
    C,C++ & Linux 2020. 6. 4. 01:43
    728x90

    함수 기능

    현재 프로세스를 대신하여 새로운 프로세스를 실행하는 함수입니다.

     

    함수 접미사 용도
    l list 형태로 인자를 입력합니다. 인자의 끝을 0 으로 표시합니다.
    v vector 형태로 인자를 입력합니다.
    e 맨 마지막 인자로 환경 변수를 입력합니다.
    p 프로세스를 현재 디렉토리(pwd) 에서 찾습니다.

     

    exec() 함수는 입력 받은 경로가 '/'로 시작하지 않으면 환경 변수에서 파일을 찾습니다.

    파일을 찾으면 실행 가능한 기계어 코드인지 판별하고, 그렇지 않으면 shell script 라고 판단하여 실행시킵니다.

    함수 원형

    #include <unistd.h>
    int execl(const char *filepath, const char *arg0, ... /* (char *) 0 */);
    int execv(const char *filepath, char *const argv[]);
    int execle(const char *filepath, const char *arg0, ... /* (char *) 0, char *const envpp[] */);
    int execve(const char *filepath, char *const argv[], char *const envpp[]);
    int execlp(const char *filepath, const char *arg0, ... /* (char *) 0 */);
    int execvp(const char *filepath, char *const argv[]);

     

    매개변수

    filepath

    실행할 프로세스의 경로를 담고 있는 문자열

    p 가 붙은 exec() 함수는 현재 작업 디렉토리 내에서 해당 프로세스를 찾습니다.

     

    arg0

    실행할 프로세스에 넘길 첫 번째 인자로, 프로세스의 이름을 담는 매개변수입니다.

     

    ...

    실행할 프로세스에 넘길 이름을 제외한 매개변수로, 그 끝을 0으로 표시합니다.

     

    argv

    실행할 프로세스에 넘길 인자 배열

    반환값

    성공 시 리턴하지 않으며, 에러 시 -1을 리턴하고 errno 를 설정합니다.

    예제

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/resource.h>
    #include <sys/time.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    
    double ssu_maketime(struct timeval *time) {
        return ((double) time -> tv_sec + (double) time -> tv_usec / 1000000.0);
    }
    
    void term_stat(int stat) {
        if (WIFEXITED(stat))
            printf("정상 종료. exit status = %d\n", WEXITSTATUS(stat));
        else if (WIFSIGNALED(stat))
            printf("비정상 종료. signal = %d\n", WTERMSIG(stat));
        else if (WIFSTOPPED(stat))
            printf("%d 시그널에 의해 중단된 프로세스.\n", WSTOPSIG(stat));
    
    }
    
    void ssu_print_child_info(int stat, struct rusage *rusage) {
        printf("Termination info follows\n");
        term_stat(stat);
        printf("user CPU time : %.2f(sec)\n", ssu_maketime(&rusage->ru_utime));
        printf("system CPU time : %.2f(sec)\n", ssu_maketime(&rusage->ru_stime));
    }
    
    int main() {
        struct rusage rusage;
        pid_t pid;
        int status;
    
        if ((pid = fork()) == 0) {
    		// find 프로그램 실행 (기본 프로그램임)
            char *args[] = {"find", "/", "-maxdepth", "4", "-name", "stdio.h", NULL};
            if (execv("/usr/bin/find", args) < 0) {
                fprintf(stderr, "execv error\n");
                exit(1);
            }
        }
    
    	// find 프로세스가 종료되기를 대기
        if (wait3(&status, 0, &rusage) == pid)
    		// find 프로세스가 어떻게 종료되었는지 그 상태를 출력
            ssu_print_child_info(status, &rusage);
        else {
            fprintf(stderr, "wait3 error\n");
            exit(1);
        }
    
        exit(0);
    }
    

    결과

     

    예제2

    // main.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main() {
        char *argv[] = {
            "ssu_execl", "param1", "param2", (char *) 0
        };
    
        printf("this is the original program\n");
        execv("./ssu_execl", argv);
        printf("%s\n", "This line should never get printed\n");
        exit(0);
    }
    
    // ssu_execl.c
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char *argv[]) {
        extern char **environ;
        char **str;
        int i;
    
        for (i = 0; i < argc; i++)
            printf("argv[%d]: %s\n", i, argv[i]);
    
        for (str = environ; *str != 0; str++)
            printf("%s\n", *str);
    
        exit(0);
    }
    

    결과

    예제3

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main() {
        if (fork() == 0) {
            execl("/bin/echo", "echo", "this is ", "message one", (char *) 0);
            fprintf(stderr, "exec error\n");
            exit(1);
        }
    
        if (fork() == 0) {
            execl("/bin/echo", "echo", "this is", "message two", (char *) 0);
            fprintf(stderr, "exec error\n");
            exit(1);
        }
    
        if (fork() == 0) {
            execl("/bin/echo", "echo", "this is", "message three", (char *) 0);
            fprintf(stderr, "exec error\n");
            exit(1);
        }
    
        printf("Parent program ending\n");
        exit(0);
    }
    

    결과

     

    예제4

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    int main() {
        char *argv[] = {
            "ssu_execl", "param1", "param2", (char *) 0
        };
    
        char *env[] = {
            "NAME = value",
            "nextname=nextvalue",
            "HOME=/home/oslab",
            (char *) 0
        };
    
        printf("this is the original program\n");
        execve("./ssu_execl", argv, env);
        printf("%s\n", "This line should never get printed\n");
        exit(0);
    }
    

    결과

     

     

     

     

     

     

     

    리눅스시스템프로그래밍 저자 : 홍지만
    https://book.naver.com/bookdb/book_detail.nhn?bid=14623672

    책에 기술된 예제 프로그램입니다. 책 내부에는 훨씬 더 많은 자료가 있습니다. (개인적으로 좋았습니다.)

    'C,C++ & Linux' 카테고리의 다른 글

    C/C++ setuid(2), setgid(2)  (0) 2020.06.04
    C/C++ wait3(2), wait4(2)  (0) 2020.06.04
    C/C++ waitid(2)  (0) 2020.06.04
    C/C++ wait(2), waitpid(2)  (0) 2020.06.04
    C/C++ vfork(2)  (0) 2020.05.24

    댓글

Designed by Tistory.