2012-10-24 3 views
1

나는 신호, 포크 및 execve로 놀고있다. 그리고 다른 장난감 프로그램을 호출하는 자식 프로세스를 만들기 위해 fork()을 사용하는 장난감 프로그램을 작성했다. 그런 다음 부모는 일정 시간 (초) 후에 기능을 중지시키는 경보를 설정합니다.C : 매개 변수로 함수를 선언하면 해당 동작이 변경됩니다 ...?

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

pid_t childPid; 

pid_t Fork() 
{ 
    pid_t pid; 

    if ((pid = fork()) < 0) 
     printf("Error:\n"); 
    return pid; 
} 

void killhandler(int sig) 
/*This will be called when we receive a SIGALRM*/ 
{ 
    int status; 
    printf("\nAssassin: *ksh* Received order to kill process: %d\n", (int)childPid); 
    if (!(status = kill(childPid, SIGKILL))) { 
     printf("Assassin: Clean and discreet. My work here is done. *ksh*\n"); 
    } else { 
     printf("Assassin: He got away!\n"); 
    } 
} 

void forkyMcFork() 
{ 
    pid_t pid; 
    int status; 
    /*Generate information for new program*/ 
    char* argv[] = {"problem5", "Hello"}; 
    char* envp[] = {"PANTS=JEANS"}; 
    char* func = "problem5"; 

    /* Create child process, child process calls executable "problem5" */ 
    if ((pid = Fork()) == 0) { 
     printf("Child: I am a child! Woohoo!\n"); 
     if (execve(func, argv, envp) < 0) 
      printf("Child: error, %s not found\n", func); 
     while(1); 
    } 
    else { 
     /* Parent process sets alarm, then prints a message depending on exit status*/ 
     childPid = pid; 
     alarm(3); 
     printf("Parent: I am the parent!\n"); 
     waitpid(-1, &status, 0); 
     if (!WIFEXITED(status)) { 
      printf("Parent: Oh no, what happened to my baby!!!\n"); 
      exit(0); 
     } else { 
      printf("Parent: Child came home without any problems.\n"); 
     } 
    } 
} 

int main(int argc, char const *argv[]) 
{ 
    signal(SIGALRM, killhandler); 
    forkyMcFork(); 
    return 0; 
} 

여기에 이상한 부분이있다 : 나는 매개 변수를 고려하지 않기 때문에 기능 forkyMcFork()를 선언 한 후 수동으로 alarm()에 대한 인수를 설정하면, 그것은 내가 기대하는 것처럼 단지 작동 : 자식 프로세스가 problem5을 시작을 요청하는 사용자로부터 어떤 입력 한 다음 삼초, killhandler 실행 한 후, 자식 프로세스를 발견하고 그것을 죽이고 : 내가 대신 forkyMcFork(int secs) 선언하고 alarm(secs)에 의해 호출 할 필요가 외부 프로그램을 사용하는 경우,

$ ./forkfun 
Parent: I am the parent! 
Child: I am a child! Woohoo! 
Please type name. If finished press enter: Haha 
Please type name. If finished press enter: 
Assassin: *ksh* Received order to kill process: 42409 
Assassin: Clean and discreet. My work here is done. *ksh* 
Parent: Oh no, what happened to my baby!!! 
$ 

그러나 execve() 하위 프로그램의 문을 찾을 수 없습니다. 알람이 예상대로 실행되므로 몇 초가 지나면 하위 프로세스가 액세 스됩니다. forkyMcFork 여부를 void을 복용으로 선언

$ ./forkfun 
Parent: I am the parent! 
Child: I am a child! Woohoo! 
Child: error, problem5 not found 

Assassin: *ksh* Received order to kill process: 42400 
Assassin: Clean and discreet. My work here is done. *ksh* 
Parent: Oh no, what happened to my baby!!! 
$ 

그래서 명확하게하기 위해, 여기에 코드 만 차이가있다 : 여기

은 비 작동 코드입니다 :

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

pid_t childPid; 

pid_t Fork() 
{ 
    pid_t pid; 

    if ((pid = fork()) < 0) 
     printf("Error:\n"); 
    return pid; 
} 

void killhandler(int sig) 
/*This will be called when we receive a SIGALRM*/ 
{ 
    int status; 
    printf("\nAssassin: *ksh* Received order to kill process: %d\n", (int)childPid); 
    if (!(status = kill(childPid, SIGKILL))) { 
     printf("Assassin: Clean and discreet. My work here is done. *ksh*\n"); 
    } else { 
     printf("Assassin: He got away!\n"); 
    } 
} 

void forkyMcFork(int secs) 
{ 
    pid_t pid; 
    int status; 
    /*Generate information for new program*/ 
    char* argv[] = {"problem5", "Hello"}; 
    char* envp[] = {"PANTS=JEANS"}; 
    char* func = "problem5"; 

    /* Create child process, child process calls executable "problem5" */ 
    if ((pid = Fork()) == 0) { 
     printf("Child: I am a child! Woohoo!\n"); 
     if (execve(func, argv, envp) < 0) 
      printf("Child: error, %s not found\n", func); 
     while(1); 
    } 
    else { 
     /* Parent process sets alarm, then prints a message depending on exit status*/ 
     childPid = pid; 
     alarm(secs); 
     printf("Parent: I am the parent!\n"); 
     waitpid(-1, &status, 0); 
     if (!WIFEXITED(status)) { 
      printf("Parent: Oh no, what happened to my baby!!!\n"); 
      exit(0); 
     } else { 
      printf("Parent: Child came home without any problems.\n"); 
     } 
    } 
} 

int main(int argc, char const *argv[]) 
{ 
    signal(SIGALRM, killhandler); 
    forkyMcFork(5); 
    return 0; 
} 

그리고 여기에 그 출력의 ,이 경우 작동하거나, int secs을 취하는 것으로 간주합니다. 무슨 일이야?

+0

'execve'에서 오류가 발생하면'errno'의 값을 출력하거나 ['strerror'] (http://linux.die.net/man/3/strerror)를 사용하여 에러 코드의 인쇄 가능한 텍스트 –

+2

또한 성공한 프로그램 대신 _fails_ 프로그램을 보여주십시오. –

+4

ForkyMcFork()의 ​​argv 및 envp 변수 끝에 null 인수를 추가하십시오. 어느 버전의 운이 좋든 운이 좋을 수도 있습니다. – Duck

답변

1

오리 코멘트에 답변이 있었다 - 그래서 그냥 요약 :

INT의에서 execve는 (const를 문자 * [] argv를 파일 이름, 숯불 *의 CONST, 숯불 * const를 envp는 []);

argv은 새 프로그램에 전달되는 인수 문자열의 배열입니다. envp 은 일반적으로 환경으로 새 프로그램에 전달되는 문자열 key = value의 배열입니다. argv와 envp는 모두 널 포인터로 끝나야합니다.

그래서 NULL을 추가하여 인 경우 envp을 추가하는 것이 좋습니다.