2016-09-04 6 views
3

내 프로그램에서 fork 및 exec 시스템 호출을 사용해야합니다. exec는 자식 프로세스를 변경하여 다른 명령을 인수로 사용하고 해당 명령을 실행합니다. ./myexecv cat etc/motd 아무 일을 실행하지 후이 내 현재 코드포크 및 execve 세그먼트 화 오류

extern char **environ;  /* environment info */ 
main(int argc, char **argv) { 
    /* argc -- number of arguments */ 
    /* argv -- an array of strings */ 

    char *argvNew[argc + 1]; 
    int pid; 

    for(int i=0; i<argc; i++){ 
     argvNew[i] = argv[i]; 
    } 
    argvNew[argc + 1] = NULL; 
    printf("After For: %s\n",argvNew[0]); 
    printf("After For: %s\n",argvNew[1]); 
    printf("After For: %s\n",argvNew[2]); 
    printf("After For: %s\n",argvNew[3]); 


    if ((pid = fork()) < 0) { 
     fprintf(stderr, "Fork error%sstrerror\n", strerror(errno)); 

     exit(1); 
    } 
    else if (pid == 0) { 
     /* child process */ 
     if (execve(argvNew[0], argvNew, environ) < 0) { 
      fprintf(stderr, "Execve error%d %s\n",errno,strerror(errno)); 
      exit(1); 
     } 
    } 
    else { 
     /* parent */ 
    wait(0);  /* wait for the child to finish */ 
    } 

} 

./myexec cat /etc/motd 

입니다 : 예를 들어, 오늘의 메시지를 표시합니다 그냥 인쇄 문. 앞으로 어떤 조언이 필요합니까?

+0

절대 인수 목록을 복사 할 필요가 없습니다. 'execv()'대신에'execve()'를 사용하라는 정식 명령이 없다면 그것을 사용하십시오. 전체 코드는'execv (argv [1], & argv [1]);''- 포크 없음, 복사 안 함, 기다리지 않음, 그 밖의 아무것도 없다. 원래 코드의 fork/exec/wait 체제의 유일한 "이점"은 실행 된 명령이 성공했는지 여부에 관계없이 부모로부터의 리턴 코드가 항상 0이라는 것입니다 (C99 또는 더 나은 컴파일러를 사용한다고 가정 할 때 떨어지는 main의 끝에서'return 0'과 동등하지만'main'은 명백한'int' 리턴 타입을 가져야합니다). –

+0

답변 해 주셔서 감사합니다. 그러나 명령을 작성한 후에도 아무 일도 일어나지 않습니다. ~/Documents $ ./myfork ls -l 이후 대상 : ls 이후 대상 : -l 이후 : (null) 이후 : (null) 다음 오류 메시지가 없습니다. 디렉토리 – SolRac

+0

아 ...'execv()'또는'execve()'를 사용하면 실행 파일의 절대 이름 (또는 현재 디렉토리에 상대적인 이름)을 지정해야합니다. './myexec/bin/cat/etc/motd' (또는'cat /'이있는 곳이면'./myexec/usr/bin/cat/etc/motd')를 시도해보십시오. 그게 효과가있다. 'cat'에 대해 쉘과 같은 PATH 기반 검색을 수행하려면'execvp()'를 사용하십시오. - 코드를 찾을 수 있고 정말로 원한다면 [execvpe()'] (http : // stackoverflow. co.kr/questions/7789750), 환경을 변경하지 않으므로 환경 설정 변종을 사용할 필요가 없습니다. –

답변

2

표시된 코드에 여러 가지 버그가 있습니다.

그것의 액면가에
for(int i=0; i<argc; i++){ 
      argvNew[i] = argv[i]; 
    } 
    argvNew[argc+1] = NULL; 

의 NULL 할당은 잘못이며, argvNew

char *argvNew[argc + 1]; 

로 선언되어 있기 때문에 그래서 배열이 argvNew[0]argvNew[argc]을 통해 값을 포함하는 정의되지 않은 동작이 발생할 것이며, argvNew[argc+1]=NULL; 과거를 실행 정의되지 않은 동작을 초래하는 배열의 끝. 이것은 분명히

argvNew[argc] = NULL; 

해야하지만 때문에 심지어는 잘못된 것 :

execve(argvNew[0], argvNew, environ); 

argvNew[0]이 실행되는이 프로그램의 이름 인 argv[0]에서 복사됩니다. 이것은 하위 프로세스에서 동일한 프로그램을 포크하고 실행합니다.

당신은 자신을 위해 폭탄 테러를 당하게 될 것입니다. 공유 서버 인 경우 시스템 관리자를 아주 미친 듯이 만듭니다.

방정식에서 argv[0]을 제거하고 argv[1] 이상을 복사해야합니다. 정확한 루프 및 복사된다 : execve()

int pid; 
    char *argvNew[argc]; 

    for(int i=1; i<argc; i++){ 
      argvNew[i-1] = argv[i]; 
    } 
    argvNew[argc-1] = NULL; 
+0

복사의 이점은 무엇입니까? 왜 단지'execve (argv [1], & argv [1], environ); 또는'execv (argv [1], & argv [1]); –

+0

이점이 없습니다. 그러나 이것은 단지 [mcve] 일 뿐이며, OP의 실제 코드는 argv에 대한 추가 조작을 수행 할 수 있습니다. –

1

발신 파라미터 실행할 파일명 최초 파라미터를 필요로한다. 불행히도 argvNew[0]을 전달하면 argv[0]과 같은 값입니다. 즉, 자신의 프로그램을 호출하고 다시 호출해야하며 스크립트는 절대 호출하지 말아야합니다. 매개 변수를 하나씩 이동해야합니다.

... 
for(int i=1; i<argc; i++){ 
    argvNew[i-1] = argv[i]; 
} 
argvNew[argc-1] = NULL; 
... 
+0

복사의 이점은 무엇입니까? 왜 단지'execve (argv [1], & argv [1], environ); 또는'execv (argv [1], & argv [1]); –

+0

@JonathanLeffler 우수 제안 !! 나는 OP가 사건을 단순화했다고 생각했기 때문에 사본을 보관했습니다. 나는 현실적으로 그는 몇몇 매개 변수를 추가/변경/제거 할 것이라고 상상한다. 그렇지 않은 경우이 프로그램에서 추가 한 가치는 무엇입니까? – Christophe