【问题标题】:Create linux environment in C using execl and fork() [closed]使用 execl 和 fork() 在 C 中创建 linux 环境 [关闭]
【发布时间】:2013-02-27 13:46:47
【问题描述】:

我创建了一个类似于 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;
}

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

【问题讨论】:

  • 学习使用像gdb这样的调试器。使用gcc -Wall -g 编译您的程序。并清除您的 a[5] 数组(应该更大,或者一些堆分配的数据)。还可以查看小型免费软件外壳的源代码(例如sash
  • 另外a[0] != "exit" 可能不是你想要的。使用strcmp
  • 你真的需要花几个小时来阅读一本好的 C 编程书籍。然后阅读一本好的 Linux 编程书籍,如advancedlinuxprogramming.com;花一两天时间阅读(也许在图书馆)。

标签: c linux shell command exec


【解决方案1】:

行:

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

a[i] 设置为字符串中的指针,您正在修改该指针,最终可能会删除临时NUL 字符(来自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)

最后一件事,您传递给execvpargv[] 数组必须有一个最终终止的NULL 指针。这是合同的一部分,因此您需要确保在致电 execvp 之前将其放入。

【讨论】:

  • 当我执行strdup (strtok(s," ")); 时,我输入的任何内容都会给我一个空白行。我把我所有的比较语句都改成了strcmp。我不明白你关于 execvp 的最后几点。
【解决方案2】:

while 循环 while (a[0] != "exit") 永远不会终止。您正在比较指针(内存地址)。你可能想了解strcmp()

if 语句if(a[0] = "cd") 似乎也不是我认为您尝试做的。您正在将指向"cd" 的指针分配给a[0]。如果您使用编译器诊断程序,就会发现这个常见错误(可能的意图是使用 ==,这也不起作用 - 再次,strcmp() 是用于字符串比较的东西)。

【讨论】:

  • so strcmp( a[0], char *string1) 其中 string1 设置为退出?还有一张用于 cd 吗?
  • 如果两个字符串相等,则更简单的strcmp(a[0], "exit") 返回 0(char 数组包含完全相同的字符,直到终止 NUL)。
  • 我与strcmp 进行了所有比较,但是当我输入任何命令(包括退出)时都会出现分段错误。
  • 是时候学习如何使用调试器了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多