我的程序应该使用fork和exec系统调用。 exec应该更改子进程,以便它将另一个命令作为参数并执行 那个命令。例如,要显示当天的消息:
./myexec cat /etc/motd
这是我目前的代码
extern char **environ; /* environment info */
main(int argc, char **argv) {
/* argc -- number of arguments */
/* argv -- an array of strings */
char *argvNew[argc + 1];
int pid;
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc + 1] = NULL;
printf("After For: %s\n",argvNew[0]);
printf("After For: %s\n",argvNew[1]);
printf("After For: %s\n",argvNew[2]);
printf("After For: %s\n",argvNew[3]);
if ((pid = fork()) < 0) {
fprintf(stderr, "Fork error%sstrerror\n", strerror(errno));
exit(1);
}
else if (pid == 0) {
/* child process */
if (execve(argvNew[0], argvNew, environ) < 0) {
fprintf(stderr, "Execve error%d %s\n",errno,strerror(errno));
exit(1);
}
}
else {
/* parent */
wait(0); /* wait for the child to finish */
}
}
运行./myexecv cat etc/motd
后没有任何反应;只是印刷声明。有什么建议吗?
答案 0 :(得分:2)
显示的代码中存在多个错误。
for(int i=0; i<argc; i++){
argvNew[i] = argv[i];
}
argvNew[argc+1] = NULL;
在它的面值上,NULL赋值是错误的,并且会导致未定义的行为,因为argvNew
被声明为
char *argvNew[argc + 1];
因此,数组包含值argvNew[0]
到argvNew[argc]
,并且argvNew[argc+1]=NULL;
在数组末尾之外运行,导致未定义的行为。这显然应该是
argvNew[argc] = NULL;
但即便如此也是错误的,因为:
execve(argvNew[0], argvNew, environ);
argvNew[0]
是从argv[0]
复制的,这是正在执行的程序的名称。这将在子进程中分叉并运行相同的程序。
你最终会自行分叉。如果这是一个共享服务器,你将使系统管理员非常生气。
您需要从等式中删除argv[0]
,然后仅复制argv[1]
,然后再打开。正确的循环和副本是:
int pid;
char *argvNew[argc];
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
答案 1 :(得分:1)
execve()
的调用参数要求第一个参数是要执行的文件名。不幸的是,您传递了argvNew[0]
,其值与argv[0]
相同。这意味着您再次调用并调用自己的程序,而不是脚本。您需要将参数移动一个:
...
for(int i=1; i<argc; i++){
argvNew[i-1] = argv[i];
}
argvNew[argc-1] = NULL;
...