Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
exec函数仅运行一些命令,赢得';t运行回声_C_Exec_Echo - Fatal编程技术网

exec函数仅运行一些命令,赢得';t运行回声

exec函数仅运行一些命令,赢得';t运行回声,c,exec,echo,C,Exec,Echo,我试图通过exec函数族运行命令行参数(特别是echo)。如果我编写自己的可执行文件并运行它,我可以让execv函数运行,但是如果我尝试运行touch或echo,它将返回-1 #include <stdio.h> #include <unistd.h> // exec functions #include <sys/types.h> // pid_t #include <sys/wait.h> #define HIGH 1 #define LOW

我试图通过exec函数族运行命令行参数(特别是echo)。如果我编写自己的可执行文件并运行它,我可以让execv函数运行,但是如果我尝试运行touch或echo,它将返回-1

#include <stdio.h>
#include <unistd.h> // exec functions
#include <sys/types.h> // pid_t
#include <sys/wait.h>

#define HIGH 1
#define LOW 0

int digitalWrite(int pin, short type) {

    pid_t pid = fork();
    if (pid == 0) {
        printf("pid == %i\n", pid);
        if (type == HIGH) {
            char* args[] = {"echo", "1", ">", "/sys/class/gpio/gpio67/value", NULL};
            int val = execv(args[0], args);
            printf("ran function execl, %i\n", val);
        } else {
            printf("Unable to do anything but set pin to HIGH\n");
        }
    } else if (pid < 0) { // pid < 0
        printf("fork failed\n");
    }

    wait(NULL);
}

int main() {

    printf("Starting digitalWrite\n");

    digitalWrite(0, HIGH);

    printf("Completed digitalWrite()\n");

    return 0;
}
命令
echo 1>/sys/class/gpio/gpio67/value
本身在终端中运行良好,如果我创建一个本地文件(即触摸tmpfile.txt)并尝试运行
echo hi>tmpfile.txt
,它将在我的命令行中按预期运行,但不会在程序中运行

我一定是不理解execv的一些东西,任何帮助都将不胜感激

execv()
不搜索
PATH
环境变量以查找可执行文件。Per(添加粗体文本):

用于
execlp()
execvp()
execvpe()
的特殊语义

execlp()
execvp()
execvpe()
函数复制操作 如果指定了 文件名不包含斜杠(/)字符

因此,如果传递的文件名不包含
/
字符,这三个变量将搜索
路径
环境变量

您正在使用的是
execv()
,它不是这三个选项之一。因此,
execv()
搜索
路径
环境变量

由于当前工作目录不包含名为
echo
的可执行文件,
execv()
失败


您需要使用
execvp()
per

在这种情况下,我不完全确定您为什么要使用
exec
系列来运行外部程序。C标准库提供了足够的文件I/O功能

例如,您可以简单地
fopen
fprintf
fclose
文件,而无需启动另一个外部进程来完成该工作:

int bytesWrit = 0;
FILE *gpioHndl = fopen("/sys/class/gpio/gpio67/value");
if (gpioHndl != NULL) {
    bytesWrit = fprintf(gpioHndl, "1\n");
    fclose(gpioHndl);
}
if (bytesWrit != 2) {
    HandleError();
}
这可能是做您想做的事情的首选方法,也就是简单地将固定值写入文件


关于为什么你的
execv
调用不起作用(尽管如果你接受我上面的建议,这是完全不相关的),有几件事你需要注意

首先,虽然有些命令实际上是磁盘上的文件,您可以
exec
,但其他命令可能是内部
bash
命令(a)。例如,在我的系统上:

pax:~$ type ftp
ftp is /usr/bin/ftp

pax:~$ type echo
echo is a shell builtin
解决这一问题的一种方法是运行实际的
bash
可执行文件(这是一个磁盘上的命令,可以通过
exec
执行),告诉它运行内部的
echo
命令。从命令行:

pax:~$ bash -c 'echo xyzzy'
xyzzy
其次,如果要使用重定向,这通常是由shell完成的,而不是
exec
调用或单个可执行文件

尝试通过
exec
系列执行重定向通常只会导致
>somefile
作为文本参数传递给可执行文件(在
argv
数组中),而不用于将标准输出附加到文件。换句话说,除非可执行文件专门处理重定向,否则它将无法工作,这是很少见的

因此,这意味着您必须使用重定向运行shell,并在执行这些重定向后让它运行可执行文件,即使该命令不是内部命令

第三,如果要搜索可执行文件的路径,
execvp
是您想要的调用,而不是
execv
(后者只使用您显式提供的文件,可以是当前工作目录的相对路径,也可以是像
/bin/ls
这样的绝对路径)。因此,在您的情况下,您应该:

  • 使用
    execvp
    搜索路径;或
  • 使用
    execv
    完全指定路径


(a)
echo
命令(虽然它是
bash
-internal)也可以作为一个单独的可执行文件提供(我相信Posix需要这样做),因此这在这里可能不是问题。如果您希望它们在更深奥的参数方面表现完全相同,则可能会出现问题:-)

执行的第一个参数是要执行的文件。与shell不同,
execv
不会搜索环境变量
PATH
指示的目录,因此需要为其提供可执行文件的完整路径。除非当前工作目录中有一个名为
echo
的可执行文件,
execv(“echo”,…)
将失败并出现“未找到文件”错误。(使用
perror
获得更好的错误消息)

如果要像shell一样搜索可执行文件,请使用
execvp
。但是请注意,您的shell可能作为内置命令执行
echo
,因此它与shell使用的
echo
不同。在这种情况下,没关系

一旦你解决了这个问题,你会遇到一个不同的问题。由于您只是使用参数调用命令行实用程序,而不是使用shell,因此参数
“>”
只是一个参数。它是处理重定向(以及管道、引用和其他一些有用的东西)的shell。因此,您所要完成的就是将这三个参数发送到stdout

您可以使用
system
函数使用shell执行命令,也可以在执行
execvp
之前通过
freopen
在您的孩子中设置stdout来设置重定向

您可以使用
man
命令获得大量关于系统接口的信息。例如,要了解
freopen
的功能,请使用
man-freopen
。您也可以在internet上阅读手册页,例如,但是您自己系统上的文档就在那里,并且也适用于t的实际版本
pax:~$ bash -c 'echo xyzzy'
xyzzy
char* args[] = {"/bin/echo","echo", "1", ">", "/sys/class/gpio/gpio67/value", NULL};
char* args[] = {"/bin/sh", "sh","-c", "/bin/echo 1 > /sys/class/gpio/gpio67/value", NULL};