2013-07-10 3 views
2

몇가지 기본적인 기능을 가진 자기 자신의 리눅스 쉘을 구현 하려다가 당연히 파이프를 구현할 때가 왔습니다. 좀 더 구체적으로 말하자면, 배관은 대부분의 경우 작동하지만, 마지막 인자는 없어집니다. 예를 들어 내가 명령을 실행할 경우커스텀 리눅스 쉘에서 파이핑하기

ps ax | grep ps 

grep 명령이 ps에서 삭제 된 후 내 셸에 ps가 삭제되었습니다. 그래서 그 대신 당신의 전형적인 리눅스 쉘

339 ?  S  0:00 upstart-udev-bridge --daemon 
497 ?  Ss  0:00 /usr/sbin/cupsd -F 
503 ?  S<  0:00 [kpsmoused] 
720 ?  S  0:00 upstart-socket-bridge --daemon 
5541 pts/0 R+  0:00 ps ax 
5542 pts/0 S+  0:00 grep --colour=auto ps 

를 사용하여 그림과 같이이 출력의 당신은 당신이 일치하는 패턴 PS 검색하지 않는이 경우이

339 ?  S  0:00 upstart-udev-bridge --daemon 
497 ?  Ss  0:00 /usr/sbin/cupsd -F 
503 ?  S<  0:00 [kpsmoused] 
720 ?  S  0:00 upstart-socket-bridge --daemon 
5557 pts/0 R+  0:00 ps ax 

를 얻을.

내가 파이프 후 모든 변수는 인수의 두 번째 세트에서 여전히 있는지 확인했습니다

void mypipes(char* args[], int nargs) 
{ 
    pid_t pid; 
    int fd[2]; 

    char* cmdargs[nargs - 2]; 
    char* cmdargs2[nargs - 2]; 


    int i; 
    int t = 0; 
    int count = 0; 

    for(i = 0; i < nargs; i++) 
    { 
if(!strcmp(args[i], "|")) 
{ 
    //dont put into array 
    t = 1; 
} 
else if(t == 0) 
{ 
    cmdargs[i] = args[i]; 
    count++; 
} 
else if(t == 1) 
{ 
    cmdargs2[i - 3] = args[i]; 
} 
    } 


    if(count == 2) 
    { 
    pipe(fd); 
    pid = fork(); 

    if(pid == -1) 
    { 
    perror("unable to fork"); 
    exit(1); 
    } 
    if(pid > 0) 
    { 
    wait(&pid); 
    close(fd[1]); 
    close(0); 
    dup2(fd[0],0); 
    execlp(cmdargs2[0], cmdargs2[0], cmdargs2[1], NULL); 
    } 
    if(pid == 0) 
    { 
    close(fd[0]); 
    close(1); 
    dup2(fd[1],1); 
    execlp(cmdargs[0], cmdargs[0], cmdargs[1], NULL); 
    } 
    } 

    if(count == 1) 
    { 
    pipe(fd); 
    pid = fork(); 

    if(pid == -1) 
    { 
    perror("unable to fork"); 
    exit(1); 
    } 
    if(pid > 0) 
    { 
    wait(&pid); 
    close(fd[1]); 
    close(0); 
    dup2(fd[0],0); 
    execlp(cmdargs2[0], cmdargs2[1], NULL); 
    } 
    if(pid == 0) 
    { 
    close(fd[0]); 
    close(1); 
    dup2(fd[1],1); 
    execlp(cmdargs[0], cmdargs[1], NULL); 
    } 

    } 

} 

을 다음 그들이 문제이기 때문에 배관 실행하는 기능을 메인 아니라 어딘가에서 실제 파이프를 끝까지 읽지 않습니다.

여기에 잘못된 정보가 있으면 언제든지 알려 주셔서 감사합니다.

답변

1

첫 번째로 내가 놓치지 않는 한 두 샘플 출력은 모두 작동하는 것처럼 보입니다. 둘 다 'ps'가있는 행만 나열됩니다. (실제로 ps ax | grep을 실행 중이면 grep은 사용법에 대해 불평 할 것입니다.) 출력에서 볼 수있는 유일한 차이점은 두 번째가 grep 프로세스 자체를 나열하지 않지만 grep이 시작되기 전에 ps이 프로세스 목록을 잡으면 쉽게 발생할 수 있다는 것입니다.

두 번째로 wait(&pid)을 사용하는 것은 이상합니다. 자식 프로세스에 있기 때문에 하위 프로세스의 하위 프로세스가 종료 될 때까지 대기합니다. 아무 것도 없으므로 ECHILD을 반환합니다 (존재하는 경우 pid을 손자의 종료 상태로 덮어 씁니다). 거의 모든 다른 combinaation가 작동하지 않습니다 -

셋째, count과 함께 t, cmdargscmdargs2의 사용은 단지 그것을 형태 cmd1 arg1 | cmd2 arg2의인지 작동하도록하는 execlp 전화를 결정합니다. 포인트의 몇 :

  • 대신 [i -3] 파이프 후 인수를 저장하려면, 당신은 저장할 때 파이프와 cmdargs2[i-t]을 찾을 때 (예를 들어, 대신 t=1의, t=i+1을 사용하는 파이프를보고하는 위치에 기억해야 그 후 논증).
  • 함수 호출의 execvp() 버전을 살펴보고 인수 배열을 전달할 수 있습니다 (명령 줄에서 모든 요소 뒤에 NULL 요소를 추가하는 것을 기억하십시오).
관련 문제