простая оболочка с использованием execlp выглядит странно - PullRequest
1 голос
/ 08 августа 2010

Я читаю Прикладное программирование GNU / Linux 2-е издание , вы можете найти то, что читаете с здесь . После того, как я напишу код, похожий на его, но он работает странно

$ ./shell
./shell>>quit
$ ./shell
./shell>>date
Sun Aug  8 21:19:37 CST 2010
./shell>>quit
$ ./shell
./shell>>abc
execlp failed: No such file or directory
./shell>>quit
./shell>>quit
$./shell 
./shell>>abcd execlp
execlp failed: No such file or directory
./shell>>quit 
./shell>>quit

Первый и второй случаи в порядке, но третий и четвертый несколько требуют двух quit , чтобы выйти. Это не то, что я ожидаю. Я думаю, что-то не так с fork () , или waitpid () , но это все еще не решено после того, как я спросил несколько людей вокруг меня. Сейчас летнее время, то есть летний отпуск, у меня больше нет друзей, на которых можно пойти. Спасибо всегда.

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define LINE_LEN 80

int main(int argc,char* argv[])
{

 pid_t pid;
 char cmd[LINE_LEN+1]={'\0'};

 while(1)
 {
  printf("%s>>",argv[0]);
  if(fgets(cmd,sizeof(cmd),stdin)==NULL)
  {
   perror("fgets failed");
   break;
  }
  cmd[strlen(cmd)-1]='\0';
  if(strncmp(cmd,"quit",4)==0)
  {
   break;
  }
  if((pid=fork())==-1)
  {
   perror("fork failed");
   break;
  }else if(pid==0)
  {
   //TODO no option can be specified for cmd
   execlp(cmd,cmd,NULL);
   perror("execlp failed");
  }else
  {
   waitpid(pid,NULL,0);
  }
 }
 return 0;
}

Ответы [ 3 ]

3 голосов
/ 08 августа 2010

Обычно, если execlp завершается успешно, ваш дочерний процесс становится новым процессом, и, таким образом, выполнение вашего кода фактически останавливается на этом этапе.

Теперь execlp не удалось, вы распечатываете ошибку и продолжаете дочерний процесс, как будто ничего не произошло! Вы должны exit(0) дочерний, если execlp не удалось.

0 голосов
/ 08 августа 2010

Просто опубликуйте версию отладки, чтобы было ясно: в каком процессе вызывается strncmp, и когда дочерний или родительский процесс завершается

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define LINE_LEN 80

int main(int argc,char* argv[])
{

    pid_t pid;
    char cmd[LINE_LEN+1]={'\0'};

    while(1)
    {
        printf("%s>>",argv[0]);
        if(fgets(cmd,sizeof(cmd),stdin)==NULL)
        {
            perror("fgets failed");
            break;
        }
        cmd[strlen(cmd)-1]='\0';
        if(strncmp(cmd,"quit",4)==0)
        {
            printf("process :%d in strncmp equal\n",getpid());
            break;
        }
        if((pid=fork())==-1)
        {
            perror("fork failed");
            break;
        }else if(pid==0)
        {
            printf("new child:%d\n",getpid());
            //TODO no option can be specified for cmd
            execlp(cmd,cmd,NULL);
            perror("execlp failed");
            //This is critical
            //exit(0);
        }else
        {
            printf("parent:%d(his child is %d)\n",getpid(),pid);
            waitpid(pid,NULL,0);
        }
    }
    printf("process :%d exit...\n",getpid());
    return 0;
}

, просто посмотрите один случай:

./shell
./shell>>abc
parent:8356(his child is 8357)
new child:8357
execlp failed: No such file or directory
./shell>>quit
process :8357 in strncmp equal
process :8357 exit...
./shell>>quit
process :8356 in strncmp equal
process :8356 exit...
0 голосов
/ 08 августа 2010

execlp завершится ошибкой, если cmd не существует.

Как правильно сказано mvds , когда execlp завершается неудачно, вы должны выйти из дочернего процесса.Но я рекомендую не разветвляться, когда cmd не существует.

Вы можете использовать что-то вроде access (см. access (2) ) перед использованием fork, чтобы убедиться, cmd существует (в вашем PATH) и является исполняемым файлом.

...