使用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; 
} 

它使用令牌来分隔命令的参数。我试着运行它,它编译并运行,但不执行我想要的命令。我认为这可能与它创建令牌的方式有关。任何帮助都会很棒。谢谢。

+1

学习使用像gdb这样的调试器。用'gcc -Wall -g'编译你的程序。并清除你的'[5]'数组(应该更大,或者一些堆分配的数据)。还可以查看小型免费软件shell的源代码(例如'sash') – 2013-03-12 06:20:31

+5

另外'a [0]!=“exit”'可能不是你想要的。使用'strcmp'。 – cnicutar 2013-03-12 06:21:05

+1

你真的需要花几个小时才能阅读一本好的C编程书籍。然后阅读http://advancedlinuxprogramming.com/这个很好的Linux编程书籍;花一两天阅读(也许在图书馆里)。 – 2013-03-12 06:29:36

行:

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之前将其付诸实施。

+0

当我执行'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()进行字符串比较)。

+0

so'strcmp(a [0],char * string1)'哪个string1被设置为退出?和一个为CD? – 2013-03-12 06:28:11

+0

如果两个字符串相等(char数组包含完全相同的字符,直到终止'NUL'),则更简单的'strcmp(a [0],“exit”)'返回0。 – FooF 2013-03-12 06:31:21

+0

我用'strcmp'完成了所有的比较,但是当我放置任何命令(包括退出)时,就会出现分段错误。 – 2013-03-12 06:58:26