我正在尝试为学校的一个项目编写一个使用shell命令的程序。我能够编译和运行代码而不出错,但是当我输入ls
这样的命令时,什么也没有发生。我想我在execvp
中遗漏了一些东西。
我一直在尝试使用各种配置的输入。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wait.h>
#include <stdlib.h>
#define MAX_LINE 80 /* Maximum length of a command */
int main(void) {
char args[MAX_LINE / 2 + 1]; /* command line arguments */
int should_run = 1; /* Flag to determine when to exit the program */
pid_t pid;
char *myCmd;
char *tokens[40];
pid = fork();
while (should_run) {
printf("osh>");
fflush(stdout);
scanf("%s", myCmd);
int i = 0;
char *token = strtok(myCmd, " ");
while (token != NULL) {
tokens[i] = token;
i++;
token = strtok(NULL, " ");
}
if (pid < 0) {
printf("Fork Failed\n");
//exit(1);
} else
if (pid == 0) {
execvp(tokens[0], tokens);
//exit(1);
} else {
if (strcmp(tokens[i - 1], "&")) {
waitpid(pid, NULL, 0);
}
}
}
return 0;
}
2条答案
按热度按时间hts6caw31#
除了命令输入和
execvp()
参数格式的严重问题之外,您在错误的位置调用fork()
。您需要为shell运行的 * 每个 * 命令fork()
一个新的子命令,因此fork
调用应该进入循环。此外,它应该在 * 打印提示符和阅读命令之后 * 进行。因为你只想让父进程来做这些事情,而不是子进程。2你不需要父进程和子进程都来解析命令。3尽管你可以依赖子进程来做这些事情,但是在父进程中做会更传统。4但肯定不是同时在父进程和子进程中。可以想象,尽管有其他错误,您的程序看起来仍然可以工作(尽管这不是不修复它们的理由),但是
fork()
的位置问题绝对是个问题,它将导致意外的额外提示,并且shell永远不会尝试执行多个命令(尽管您可能没有注意到,部分原因是您没有检查几个键函数调用的返回值)。8i9zcol22#
只为指针分配内存。指针具有不确定的值,即它可能指向任何对象,任何试图取消引用具有错误值的指针的操作都将导致未定义的行为。
只有在显式指定初始值时,才初始化自动和动态分配的对象;否则,它们最初具有不确定的值(通常,无论存储器中碰巧存在什么样的位模式,其甚至可能不表示该类型的有效值)。
随后对
scanf()
的调用会调用未定义的行为,因为没有为该字符串分配内存。如果没有任何命令会超过80个字符,如以下注解所述:
您可以分配
char
的array[80]
,然后将其传递给scanf()
。为了限制输入,可以指定一个宽度说明符,如下所示:
不要使用
scanf()
。使用fgets()
。使用scanf()
,它只会获取第一个空格分隔的标记(例如,对于Hello World的输入,scanf()
只会返回Hello)。-@Craig Esteyexecvp
的指针数组应以空值终止:**execv()、execvp()和execvpe()函数提供一个指针数组,指向以空值结尾的字符串,这些字符串表示新程序可用的参数列表。按照约定,第一个参数应指向与正在执行的文件关联的文件名。指针数组必须以空值指针结尾。
缺少代码:
在
while
循环之后。旁白:A shell in C - Tutorial和Beej's guide to UNIX Interprocess Communication可能有助于详细说明@John在回答中指出的内容。