使用execl和fork创建linux环境()
我创建了一个类似Linux环境的程序。你输入一个命令,它为你做。使用execl和fork创建linux环境()
#include <stdio.h>
#include <string.h>
int main()
{
int pid;
int status;
printf("Enter command: ");
char s[256];
fgets(s,256,stdin);
const char *a[5];
int i = 0;
char* token = strtok(s, " ");
while(token)
{
a[i] = strtok(s," ");
i++;
}
while (a[0] != "exit")
{
if(a[0] = "cd")
{
chdir(a[1]);
}
else
{
pid = fork();
if (pid == 0)
{
execvp(a[0],a);
}
if(pid > 0)
{
wait(&status);
}
}
}
return 0;
}
它使用令牌来分隔命令的参数。我试着运行它,它编译并运行,但不执行我想要的命令。我认为这可能与它创建令牌的方式有关。任何帮助都会很棒。谢谢。
行:
a[i] = strtok(s," ");
套a[i]
字符串内的指针,删除你正在修改并最终可能会临时NULL字符(从strtok
)。
您可能也想尝试:
a[i] = strdup (strtok (s," "));
代替。
让我进一步解释。假设我们有命令(因为它存在于内存中):
ls -al xyzzy\0
当你strtok
,它几乎肯定被改为:
ls\0-al xyzzy\0
^
,然后它给你s
(由^
表示)从strtok
返回并放入a[0]
。下一次通过,它改变了字符串:
ls -al\0xyzzy\0
^
,并为您的^
和地方表示到a[1]
地址。不幸的是,a[0]
现在指向字符串"ls -al"
最终,该字符串将恢复到原来的状态,你的指针,同时指向正确的地址,不会有像您期望的字符串以空值终止(除最后一个)。
所以你结了:
a[0] = "ls -al xyzzy"
a[1] = "-al xyzzy"
a[2] = "xyzzy"
使用strdup
,你让每串的副本(当时当字符串是如您所愿,一个字),其中不会被字符串令牌代码中稍后的操作修改。
但是请记住,当您完成所有这些字符串时,请释放所有这些字符串。
您可以使用此代码作为基础:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void) {
char str[256], *word[20];
int i, num, len;
printf ("Enter command: ");
fgets (str, sizeof (str), stdin);
num = 0;
word[num] = strtok (str, " ");
while (word[num] != NULL) {
word[num] = strdup (word[num]);
len = strlen (word[num]);
if (strlen (word[num]) > 0)
if (word[num][len-1] == '\n')
word[num][len-1] = '\0';
word[++num] = strtok (NULL, " ");
}
for (i = 0; i < num; i++) {
printf ("%d: [%s]\n", i, (word[i] == NULL) ? "<<null>>" : word[i]);
free (word[i]);
}
return 0;
}
和下面的记录表明它在行动:
Enter command: ls -al xyzzy | grep -v plugh
0: [ls]
1: [-al]
2: [xyzzy]
3: [|]
4: [grep]
5: [-v]
6: [plugh]
此外,比较C字符串正确的做法是不:
if (a[0] = "cd")
,因为它比较地址,,即使后备内容相同,这些地址也可能不同。你应该使用类似:
if (strcmp (a[0], "cd") == 0)
以及一个最终的东西,argv[]
数组传递给execvp
必须有一个最终终止NULL指针。这是合同的一部分,因此您需要确保在拨打execvp
之前将其付诸实施。
当我执行'strdup(strtok(s,“”));'我放入的任何东西都给我一个空行。我把我所有的比较语句都重新命名为'strcmp'。我不明白你关于execvp的最后一点。 – 2013-03-12 06:46:27
while循环while (a[0] != "exit")
将永不终止。你正在比较指针(内存地址)。您可能需要阅读约strcmp()
。
if语句if(a[0] = "cd")
似乎也不是我认为你试图做的。您正在将指针指向"cd"
至a[0]
。如果您使用编译器诊断(如果使用==
而不是使用==
,则可能会遇到这种常见错误 - 再次使用strcmp()
进行字符串比较)。
so'strcmp(a [0],char * string1)'哪个string1被设置为退出?和一个为CD? – 2013-03-12 06:28:11
如果两个字符串相等(char数组包含完全相同的字符,直到终止'NUL'),则更简单的'strcmp(a [0],“exit”)'返回0。 – FooF 2013-03-12 06:31:21
我用'strcmp'完成了所有的比较,但是当我放置任何命令(包括退出)时,就会出现分段错误。 – 2013-03-12 06:58:26
学习使用像gdb这样的调试器。用'gcc -Wall -g'编译你的程序。并清除你的'[5]'数组(应该更大,或者一些堆分配的数据)。还可以查看小型免费软件shell的源代码(例如'sash') – 2013-03-12 06:20:31
另外'a [0]!=“exit”'可能不是你想要的。使用'strcmp'。 – cnicutar 2013-03-12 06:21:05
你真的需要花几个小时才能阅读一本好的C编程书籍。然后阅读http://advancedlinuxprogramming.com/这个很好的Linux编程书籍;花一两天阅读(也许在图书馆里)。 – 2013-03-12 06:29:36