C & LINUX

C / LINUX execl(3), execv(3), execle(3), execve(2), execlp(3), execvp(3)

Ocean_ 2022. 5. 2. 21:33

함수 기능

exec 계열 함수는 현재 수행되고 있는 프로세스를 대신하여 새로운 프로세스를 수행시키는 함수

 

-l argument list

-v argument vector

-e 환경변수 유무

-p p있으면 filename 없으면 pathname

 

ex ) execvp 는 argument vector + filename

 

함수 원형

#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[]);

리턴 값 : 성공 시 리턴하지 않음 , 에러시 -1 리턴

함수 파라메터

filepath

실행할 프로세스의 경로

 

arg0

프로세스에 넘길 첫 번째 인자

 

argv

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

함수 예제

execl1 & test

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

int main(void){
    printf("this is the original program\n");
    execl("./ssu_execl_test_1","ssu_execl_test_1","param1","param2","param3",(char*)0);
    /*
        현재디렉토리의 ssu_execl_test_1이라는 파일에 리스트로 인자를 주어 실행한다.
        인자로 "ssu_execl_test_1","param1","param2","param3"을 넘겨주면서 실행한다.
    */
    printf("%s\n", "this line should never get printed\n");
    exit(0);
}
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char*argv[]){
    extern char**environ;
    char **str;
    int i;
    /*
     인자로 "ssu_execl_test_1","param1","param2","param3" 이것을 받았기에 순서대로 argv[0] argv[1] argv[2] argv[3] 이다.
     이것들이 출력되고 환경변수가 출력된다.
    */
    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);
}

execl2

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

int main(void){

    /*
        fork로 새로운 자식 프로세스를 만드는데 리스트로 
        "echo", "this is","message one"
        "echo", "this is","message two"
        "echo", "this is","message three"
        를 준다. 그치만 부모 프로세스가 죽어버리고 자식프로세스만 남는 상황이기 떄문에
        프롬포트 이후에 메시지가 스케쥴링에 따라 출력된다.
    */

    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);
}

execv1

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<sys/resource.h>
#include<sys/wait.h>
double ssu_maketime(struct timeval *time);
void term_stat(int stat);
void ssu_print_child_info(int stat, struct rusage *rusage);

int main(void){
    struct rusage rusage;
    pid_t pid;
    int status;

    /*
        "/usr/bin/find" 경로로   인자로 프로세스를 생성한다.
    */
    if((pid=fork())==0){
        char *args[] = {"find","/","-maxdepth","4","-name","stdio.h",NULL};
        if(execv("/usr/bin/find",args)<0){
            fprintf(stderr,"execv error\n");
            exit(1);
        }
    }
    /*
        wait3을 통해서 종료된 프로세스의 자원사용량 정보를 얻을 수 있다.
    */

    if(wait3(&status,0,&rusage)==pid)
        ssu_print_child_info(status, &rusage);
    else{
        fprintf(stderr, "wait3 error\n");
        exit(1);
    }
    exit(0);
}

double ssu_maketime(struct timeval *time){
    return ((double)time -> tv_sec + (double)time -> tv_usec/1000000.0);
}

    /*
        WEXITSTATUS 자식프로세스의 종료된 반환값을 확인한다.
        WCOREDUMP가 정의되어있다면 WCOREDUMP(stat)?"core dumped":"no core"
        WIFSIGNALED 자식프로세스가 어떤 이유떄문에 종료되었다면 참
        WTERMSIG 자식프로세스 종료하도록한 신호를 반환
    */

void term_stat(int stat){
    if(WIFEXITED(stat))
        printf("normally terminated. exit status = %d\n",WEXITSTATUS(stat));
    else if(WIFSIGNALED(stat))
        printf("abnormal termination by signal %d. %s\n",WTERMSIG(stat),
#ifdef WCOREDUMP
        WCOREDUMP(stat)?"core dumped":"no core"
#else  
        NULL
#endif
    );
    else if(WIFSTOPPED(stat))
        printf("stopped by signal %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));
}

 

execve & test

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

int main(void){
    char *argv[] = {
        "ssu_execl_test_1","param1","param2",(char *)0
    };

    char *env[]={
        "NAME = value",
        "nextname=nextvalue",
        "HOME=/home/oslab",
        (char *)0
    };

    printf("this is the original program\n");

    /*
        exec 계열에서 vector로 환경변수를 넣어서 프로세스를 수행시킨다.
        argv 와 env를 모두 vector로 미리 입력해놓고 넣어서 사용.
    */
    execve("./ssu_execl_test_1", argv, env);
    printf("%s\n","This line should never get printed\n");
    exit(0);
}
#include<stdio.h>
#include<stdlib.h>

int main(int argc, char*argv[]){
    extern char**environ;
    char **str;
    int i;
    /*
     인자로 "ssu_execl_test_1","param1","param2","param3" 이것을 받았기에 순서대로 argv[0] argv[1] argv[2] argv[3] 이다.
     이것들이 출력되고 환경변수가 출력된다.
    */
    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);
}

함수 결과

execl1

execl2

execv1

 

execve

 

리눅스시스템 프로그래밍 - 홍지만 저

교재 내에 있는 예제를 바탕으로 작성한 글 입니다.