使用execl和fork()在C中创建linux环境

使用execl和fork()在C中创建linux环境,c,linux,shell,command,exec,C,Linux,Shell,Command,Exec,我创建了一个类似于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(tok

我创建了一个类似于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;
}
#包括
#包括
int main()
{
int-pid;
智力状态;
printf(“输入命令:”);
chars[256];
fgets(s,256,stdin);
常量字符*a[5];
int i=0;
char*token=strtok(s,“”);
while(令牌)
{
a[i]=strtok(s,“”);
i++;
}
while(a[0]!=“退出”)
{
如果(a[0]=“cd”)
{
chdir(a[1]);
}
其他的
{
pid=fork();
如果(pid==0)
{
execvp(a[0],a);
}
如果(pid>0)
{
等待(&状态);
}
}
}
返回0;
}
它使用标记来分隔命令的参数。我试着运行它,它编译并运行,但没有执行我想要的命令。我认为这可能与它创建代币的方式有关。任何帮助都会很好。谢谢。

线路:

a[i] = strtok(s," ");
a[i]
设置为字符串中的指针,您正在修改该指针,最终可能会删除临时NUL字符(来自
strtok

您可能想试试:

a[i] = strdup (strtok (s," "));
相反


让我进一步解释。假设我们拥有该命令(因为它存在于内存中):

当您
strtok
it时,它几乎肯定会更改为:

ls\0-al xyzzy\0
^
然后它会给你从strtok返回的
s
(用
^
表示)并放入
a[0]
。下次通过时,它将字符串更改为:

ls -al\0xyzzy\0
   ^
并提供由
^
指示的地址,并将其放入
a[1]
中。不幸的是,
a[0]
现在指向字符串
“ls-al”

最终,字符串将返回其原始状态,指针在指向正确的地址时,不会像预期的那样以null结尾字符串(最后一个除外)

因此,您将以以下方式结束:

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

此外,比较C字符串的正确方法不是:

if (a[0] = "cd")
因为这会比较地址,即使备份内容相同,地址也可能不同。您应该改为使用以下内容:

if (strcmp (a[0], "cd") == 0)


还有最后一件事,传递给
execvp
argv[]
数组必须有一个最终终止的空指针。这是合同的一部分,因此您需要确保在调用
execvp
之前,while循环
while(a[0]!=“exit”)
将永远不会终止。您正在比较指针(内存地址)。您可能需要阅读有关strcmp()的信息


if语句
if(a[0]=“cd”)
似乎也不是我认为您想要做的。您正在将指向
“cd”
的指针分配给
a[0]
。如果您使用编译器诊断(可能的意图是使用
==
而不是
=
,这也不会起作用-同样
strcmp()
是用于字符串比较的东西)。

学习使用类似
gdb
的调试器。使用
gcc-Wall-g
编译程序。然后清除
a[5]
数组(应该更大,或者一些堆分配的数据)。还可以查看小型自由软件外壳的源代码(例如
sash
),也可以查看
a[0]!=“退出”
可能不是您想要的。使用strcmp
strcmp
。阅读一本好的C编程书确实需要几个小时。然后读一本很好的Linux编程书;花一两天时间阅读(可能在图书馆里)。那么
strcmp(a[0],char*string1)
在哪个string1被设置为退出?还有一个用于cd?更简单的
strcmp(a[0],“exit”)
如果两个字符串相等,则返回0(字符数组包含完全相同的字符,直到终止
NUL
)。我与
strcmp
进行了所有比较,但我每次发出命令时都会出现分段错误,包括退出。现在真的是学习如何使用调试器的时候了我输入的任何内容都只会给我一个空行。我将所有比较语句重新命名为strcmp。我不明白你关于执行官的最后几点。
if (a[0] = "cd")
if (strcmp (a[0], "cd") == 0)