【问题标题】:simple shell using execlp goes weirdly使用 execlp 的简单 shell 很奇怪
【发布时间】:2010-08-08 13:33:10
【问题描述】:

我正在阅读GNU/Linux application programming the 2nd edition,你可以从here获得正在阅读的内容。在我写了类似于他的代码后,它的工作原理很奇怪:

$ ./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;
}

【问题讨论】:

    标签: c unix process exec fork


    【解决方案1】:

    通常,如果execlp 成功,您的子进程将成为新进程,因此您的代码的执行实际上会在该点停止。

    现在execlp 失败了,你打印出错误,然后继续子进程,就像什么都没发生一样! 如果execlp 失败,你应该exit(0) 子进程。 p>

    【讨论】:

    • 谢谢。我明白你的意思了。书中的代码没有做任何关于execlp的错误检查,所以这个修复可能会进入勘误表?
    • 绝对!如果您的书没有这样说,请记住这一点:始终检查返回值
    • (虽然,对于exec 类函数,您的代码仍然存在这一事实表明失败,因此严格来说不需要检查返回值就知道出了什么问题。。 .)
    • 再次感谢。您回答这个问题的速度如此之快。我喜欢 stackoverflow.com。如此专业,但我只是一个新手。
    【解决方案2】:

    如果cmd 不存在,execlp 将失败。

    正如mvds 说得对,当execlp 失败时,你应该退出子进程。但我建议在cmd 不存在时不要分叉。

    您可以在使用fork 之前使用access 之类的东西(请参阅access(2))以确保cmd 存在(在您的PATH 中),并且是一个可执行文件。

    【讨论】:

    • 是的,我应该在将 cmd 传递给 execlp 之前调用 access。非常感谢。
    • UPDATE:access(with X_OK) 只检查路径名,而不是文件名(即我必须用路径找出它。)
    【解决方案3】:

    把debug版本贴出来说明一下: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...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-08
      • 1970-01-01
      • 1970-01-01
      • 2019-01-03
      • 2013-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多