【问题标题】:execve() different program output printingexecve() 不同程序输出打印
【发布时间】:2021-01-30 09:46:12
【问题描述】:

我最近一直在使用execve() 系统调用,我一直在试图弄清楚为什么它会打印我调用的函数的完整路径。

例如,当用execve 调用ls 时:

/usr/bin/ls: cannot access 'nofile': No such file or directory

我的意思是,如果我想一想,这很合乎逻辑。如果我在execve 中将/usr/bin/ls 称为filename,这就是路径名。

但是为什么ls系统调用输出是这样的:

ls: cannot access[...]

和我的不一样?

我想知道是否有任何解决方案可以找出我刚刚调用的程序的“名称”,而不是打印程序的完整路径。

因为这是execve的选择而不是我的选择,至少我猜是这样,我不确定。

谢谢。

【问题讨论】:

  • 在大多数 Linux 系统上,ls 命令位于 /bin/ls 而不是 /usr/bin/ls。在您的程序中也使用strace(1)whereis(1)gdb(1)errno(3)
  • 我的意思是,它对输出有影响吗?我刚刚看到调用其他程序,如 make、cat、grep... 不会打印完整路径,而实际上只是 Usage: grep [OPTION] ....。我也不知道为什么。
  • 这是来自ls 的错误消息。它们的格式或打印内容可能因程序而异。 execve 无法改变这一点,您的问题与 execve 几乎没有关系。

标签: c linux system-calls execve


【解决方案1】:

我在下面的code 中使用了execvp 函数并构建了它:

#include  <stdio.h>
#include  <sys/types.h>

void  parse(char *line, char **argv)
{
     while (*line != '\0') {       /* if not the end of line ....... */ 
          while (*line == ' ' || *line == '\t' || *line == '\n')
               *line++ = '\0';     /* replace white spaces with 0    */
          *argv++ = line;          /* save the argument position     */
          while (*line != '\0' && *line != ' ' && 
                 *line != '\t' && *line != '\n') 
               line++;             /* skip the argument until ...    */
     }
     *argv = '\0';                 /* mark the end of argument list  */
}

void  execute(char **argv)
{
     pid_t  pid;
     int    status;

     if ((pid = fork()) < 0) {     /* fork a child process           */
          printf("*** ERROR: forking child process failed\n");
          exit(1);
     }
     else if (pid == 0) {          /* for the child process:         */
          if (execvp(*argv, argv) < 0) {     /* execute the command  */
               printf("*** ERROR: exec failed\n");
               exit(1);
          }
     }
     else {                                  /* for the parent:      */
          while (wait(&status) != pid)       /* wait for completion  */
               ;
     }
}

void  main(void)
{
     char  line[1024];             /* the input line                 */
     char  *argv[64];              /* the command line argument      */

     while (1) {                   /* repeat until done ....         */
          printf("Shell -> ");     /*   display a prompt             */
          gets(line);              /*   read in the command line     */
          printf("\n");
          parse(line, argv);       /*   parse the line               */
          if (strcmp(argv[0], "exit") == 0)  /* is it an "exit"?     */
               exit(0);            /*   exit if it is                */
          execute(argv);           /* otherwise, execute the command */
     }
}

现在,当我在 terminal 中运行程序时,结果是这样的(我尝试使用ls 命令):

msi@ubuntu:~/Desktop$ ./output
Shell -> ls

1.txt
2.jpg
Qt-Creator.run
.
.
.

它也适用于这个参数(ls 程序的完整路径):

Shell -> /bin/ls
1.txt
2.jpg
Qt-Creator.run
.
.
.

【讨论】:

  • 您好,感谢您的回答。我实际上发现了这个问题,它与 execve 工作所需的参数数组有关。在pathname 变量中,我给了它"/usr/bin/ls",这是正确的,但我也给了参数数组(/usr/bin/ls),这没有错,但是任何 ls 都会有问题的地方(就像我的例如),它会使用我的arguments array 中的第一个参数,这里是/usr/bin/ls 而不是ls。我基本上只是将数组中的第一个参数设置为ls
【解决方案2】:

我发现了这个问题,但由于它是在对 BattleTested - закалённый в бо 的回答中,我认为在这里回答这个问题对于遇到这个问题的人来说会更好。

基本上,要调用execve,我需要一个路径名(此处为/usr/bin/ls)、一个参数数组(其中包含作为第一个参数的程序名称,而不仅仅是参数或NULL 数组,如果没有)和环境.

这里对于ls-l 应该是:

pathname : "/usr/bin/ls"

arguments : {"/usr/bin/ls", "-l", NULL};

和您的环境(NULL 终止)。

问题是,execve() 将使用arguments array 的第一个参数,这里是/usr/bin/ls。只需将其修改为程序的名称,而不是路径,即可修复它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-05
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多