我正在编写代表Linux新外壳的代码。我要支持的命令之一正在运行一个进程 例如,如果我得到以下行
command [arguments]
然后我想将command
作为一个进程运行,直到完成运行为止。
为此,我知道我需要使用fork()
才能获得子进程并获取其PID,我的问题是我不知道它们之间的区别:
exec
,execvp
,execl
,execv
...,我不知道要使用哪个,为什么。
我当前的代码:
void External_Process(char *arguments[MAX_ARG], char* command)
{
int pID;
switch(pID = fork())
{
case -1:
perror("fork failed");
break;
case 0 :
setpgrp();
//execv(command, arguments);
//execvp(command, arguments);
//execl("/bin/bash", "/bin/bash","-c",command,NULL);
printf("smash error: > bad command %s\n" , command);
exit(-1) ;
break;
default:
return ;
}
}
谢谢!
答案 0 :(得分:0)
尝试阅读手册:https://linux.die.net/man/3/execv
节选:
说明 exec()系列函数将当前过程映像替换为新的过程映像。本手册页中描述的功能是execve(2)的前端。 (有关替换当前过程映像的更多详细信息,请参见execve(2)的手册页。)
这些函数的初始参数是要执行的文件的名称。
execl(),execlp()和execle()函数中的const char * arg及随后的省略号可以认为是arg0,arg1,...,argn。它们一起描述了一个或多个指向以空值结尾的字符串的指针的列表,这些字符串表示可用于执行的程序的参数列表。按照惯例,第一个参数应指向与正在执行的文件关联的文件名。参数列表必须以NULL指针终止,并且由于它们是可变参数函数,因此必须将该指针强制转换为(char *)NULL。
execv(),execvp()和execvpe()函数提供了一个指向以空值结尾的字符串的指针的数组,这些字符串表示新程序可用的参数列表。按照惯例,第一个参数应指向与正在执行的文件关联的文件名。指针数组必须以NULL指针终止。
execle()和execvpe()函数允许调用者通过参数envp指定执行程序的环境。 envp参数是指向以null终止的字符串的指针的数组,并且必须以NULL指针终止。其他功能从调用过程中的外部变量环境获取新过程映像的环境。
execlp()和execvp()的特殊语义
如果指定的文件名不包含斜杠(/)字符,则execlp(),execvp()和execvpe()函数会在搜索可执行文件时重复执行Shell的操作。在PATH环境变量中指定的目录路径名的冒号分隔列表中查找该文件。如果未定义此变量,则路径列表默认为当前目录,后跟confstr(_CS_PATH)返回的目录列表。 (此confstr(3)调用通常返回值“ / bin:/ usr / bin”。)
答案 1 :(得分:0)
在C语言中,您可以使用“系统”命令。 这将执行您作为函数参数输入的内容。
这里是一个例子:
system("ls -l");
如果要获取输出,可以重定向到其他源。
答案 2 :(得分:0)
摘要::在您的情况下,我建议使用execvp
。
要了解exec*
函数之间的区别,您应该阅读文档:
https://linux.die.net/man/3/exec
https://linux.die.net/man/2/execve
execl*
和execv*
之间的区别在于参数传递。 execl*
需要一个参数列表,而execv*
需要一个参数向量。
如果您在编译时知道所有参数,则参数列表很有用。在您的情况下,参数将由用户输入,并且您必须在运行时构造参数向量,因此您应该使用execv*
函数之一。
后缀为p
的函数使用PATH
环境变量来查找程序(例如"ls"
),否则,您必须指定完整路径(相对于路径的绝对路径或相对路径)。当前目录,例如"/bin/ls"
)。 Shell通常会使用PATH
,因此这似乎是您的正确选择。
后缀为e
的函数允许指定进程的环境。为简单起见,在您的情况下,我不会使用它。
这得出结论:execvp
当然,您也可以使用system
(而不是fork
/ exec*
/ wait*
),如vladxjohn的答案中所述,但是在这种情况下,您只会使用shell来解释您的命令,而不是实现基本的shell。