为什么我的 execvp() 在以下代码中不起作用?

发布于 2025-01-10 02:31:54 字数 2311 浏览 0 评论 0原文

我正在尝试使用 execvp() 来执行子进程,但它给了我以下错误,并且我无法修复它,有人可以指出我做错了什么吗?

我的代码:

#include "apue.h"
#include <sys/wait.h>

 static void    sig_int(int);       /* our signal-catching function */

int
 main(void)
{
char    buf[MAXLINE];   /* from apue.h */
pid_t   pid;
int     status;

if (signal(SIGINT, sig_int) == SIG_ERR)
    err_sys("signal error");

printf("%% ");  /* print prompt (printf requires %% to print %) */
while (fgets(buf, MAXLINE, stdin) != NULL) {
    if (buf[strlen(buf) - 1] == '\n')
        buf[strlen(buf) - 1] = 0; /* replace newline with null */

    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid == 0) {      /* child */
        execlp(buf, buf); //this line is where I am not sure if I am wrong.
        err_ret("couldn't execute: %s", buf);
        exit(127);
    }

    /* parent */
    if ((pid = waitpid(pid, &status, 0)) < 0)
        err_sys("waitpid error");
    printf("%% ");
}
exit(0);
}

void
 sig_int(int signo)
 {
     printf("interrupt\n%% ");
 }

我的预热/错误:

  shell2.c: In function ‘main’:
shell2.c:24:16: warning: passing argument 2 of ‘execvp’ from incompatible pointer type [-Wincompatible-pointer-types]
    execvp(buf, buf);
                ^~~
In file included from ../csci3800sp22/apue.3e/include/apue.h:26:0,
                 from shell2.c:1:
/usr/include/unistd.h:578:12: note: expected ‘char * const*’ but argument is of type ‘char *’
 extern int execvp (const char *__file, char *const __argv[])

预期结果:当我运行其他命令(execlp)时,它给出以下结果:

[singhrav@csci-gnode-02 ~/lab1]$ ls
Makefile  shell2  shell2.c
[singhrav@csci-gnode-02 ~/lab1]$ ./shell2
% ls
Makefile  shell2  shell2.c
% ps
  PID TTY          TIME CMD
24839 pts/1    00:00:00 tcsh
25175 pts/1    00:00:00 shell2
25204 pts/1    00:00:00 ps
% ls -l
couldn't execute: ls -l: No such file or directory

execlp()的问题是它不执行ls -l,我希望能够使用 lsps & ls -l 这就是为什么我决定使用 execvp() 但当我使用 execvp() 并运行我的 ./shell2 命令它给我以下错误:

[singhrav@csci-gnode-02 ~/lab1]$ ./shell2
% ls
couldn't execute: ls: Bad address
% ps
couldn't execute: ps: Bad address
% ls -l

I am trying to make use of execvp() to execute child processes but it gives me following error and I am unable to fix it can someone point me in direction what I am doing wrong?

My code:

#include "apue.h"
#include <sys/wait.h>

 static void    sig_int(int);       /* our signal-catching function */

int
 main(void)
{
char    buf[MAXLINE];   /* from apue.h */
pid_t   pid;
int     status;

if (signal(SIGINT, sig_int) == SIG_ERR)
    err_sys("signal error");

printf("%% ");  /* print prompt (printf requires %% to print %) */
while (fgets(buf, MAXLINE, stdin) != NULL) {
    if (buf[strlen(buf) - 1] == '\n')
        buf[strlen(buf) - 1] = 0; /* replace newline with null */

    if ((pid = fork()) < 0) {
        err_sys("fork error");
    } else if (pid == 0) {      /* child */
        execlp(buf, buf); //this line is where I am not sure if I am wrong.
        err_ret("couldn't execute: %s", buf);
        exit(127);
    }

    /* parent */
    if ((pid = waitpid(pid, &status, 0)) < 0)
        err_sys("waitpid error");
    printf("%% ");
}
exit(0);
}

void
 sig_int(int signo)
 {
     printf("interrupt\n%% ");
 }

My warming/error:

  shell2.c: In function ‘main’:
shell2.c:24:16: warning: passing argument 2 of ‘execvp’ from incompatible pointer type [-Wincompatible-pointer-types]
    execvp(buf, buf);
                ^~~
In file included from ../csci3800sp22/apue.3e/include/apue.h:26:0,
                 from shell2.c:1:
/usr/include/unistd.h:578:12: note: expected ‘char * const*’ but argument is of type ‘char *’
 extern int execvp (const char *__file, char *const __argv[])

Expected result: When I run other command (execlp) it gives me following result :

[singhrav@csci-gnode-02 ~/lab1]$ ls
Makefile  shell2  shell2.c
[singhrav@csci-gnode-02 ~/lab1]$ ./shell2
% ls
Makefile  shell2  shell2.c
% ps
  PID TTY          TIME CMD
24839 pts/1    00:00:00 tcsh
25175 pts/1    00:00:00 shell2
25204 pts/1    00:00:00 ps
% ls -l
couldn't execute: ls -l: No such file or directory

Problem with execlp() is it does not execute ls -l, I wanted to be able to use ls, ps & ls -l so that's why I decided to use execvp() but when I use execvp() and run my ./shell2 command it gives me following error:

[singhrav@csci-gnode-02 ~/lab1]$ ./shell2
% ls
couldn't execute: ls: Bad address
% ps
couldn't execute: ps: Bad address
% ls -l

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

用心笑 2025-01-17 02:31:54

您的问题有两个方面:

1.原始问题

原始 execlp() 调用不执行 ls -l 的问题在于您对 的调用>execlp,您不将命令的路径与其参数分开。

execlp() 的手册页指出:

这些函数的初始参数是要执行的文件的名称。

execl()execlp()execle() 中的 const char *arg 和后续省略号< /code> 函数可以被认为是 arg0arg1...argn。它们一起描述了一个或多个指向空终止字符串的指针的列表,这些指针表示可用于执行的程序的参数列表。按照惯例,第一个参数应该指向与正在执行的文件关联的文件名。参数列表必须以空指针终止,并且由于这些是可变参数函数,因此该指针必须强制转换 (char *) NULL


因此,在您的调用 execlp(buf, buf) 中,该函数将尝试查找具有literal名称 ls -l 的文件(包括空间!)并执行它。另请注意,参数列表必须以 (char *) NULL 指针终止,因此您需要将空白处的 buf 内容分隔为单独的标记,然后分别馈送到 execlp(),如

execlp("ls", "ls", "-l", (char *) NULL);

2 所示。 execvp 的问题

您没有明确显示它,但您似乎“盲目”切换了 execlpexecvp 不对参数进行任何更改。但是,execvp() 函数需要一个以 null 结尾的字符串数组,它是一个 char 数组的数组 em> 作为第二个参数。但是,您只需提供一个字符串,即一个简单的 char 数组作为第二个参数。因此,第二个参数的内容(字符)将被错误解释为预期字符串的地址,并访问未为进程分配的内存区域,这会导致错误地址 (= EFAULT)错误消息。

TL;DR

您必须更正程序中 exec... 函数的使用。

Your problem is two-fold:

1. The original problem

The problem why your original execlp() call doesn't execute ls -l is that in your call to execlp, you don't separate the command's path from its arguments.

The man page of execlp() states:

The initial argument for these functions is the name of a file that is to be executed.

The const char *arg and subsequent ellipses in the execl(), execlp(), and execle() functions can be thought of as arg0, arg1, ..., argn. Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program. The first argument, by convention, should point to the filename associated with the file being executed. The list of arguments must be terminated by a null pointer, and, since these are variadic functions, this pointer must be cast (char *) NULL.

So, in your call execlp(buf, buf), the function would try to locate a file with literal name ls -l (including the space!) and execute it. Also, note that the argument list must be terminated with a (char *) NULL pointer, so you would need to separate the content of buf at the whitespace into individual tokens that are then fed individually to execlp(), as in

execlp("ls", "ls", "-l", (char *) NULL);

2. The problem with execvp

You don't explicitly show it, but you seem to have "blindly" switched execlp with execvp without any changes to the arguments. However, the execvp() function expects an array of null-terminated strings, which is an array of array of char as second argument. However, you simply provide a string, i.e. a simple array of char as second argument. Hence, the content of the second argument (which are characters) will be mis-interpreted as addresses to the expected strings, and access memory regions not allocated for the process, which leads to the Bad address (= EFAULT) error message.

TL;DR

You have to correct the use of the exec... functions in your program.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文