【问题标题】:exec failed with fork() and execvp()exec 因 fork() 和 execvp() 而失败
【发布时间】:2021-02-22 02:14:56
【问题描述】:

我目前正在开发一个必须用 C 语言编写 shell 的程序。我无法让程序的 fork() 部分正常工作。这是我的代码:

void execute_func(char** tok)
{
    pid_t pid = fork();
    
    if (pid == -1)
    {
        printf("\nERROR: forking child process failed\n");
        return;
    }
    else if (pid == 0)
    {
        if (execvp(tok[0], tok) < 0)
        {
            printf("ERROR: exec failed\n");
        }
        exit(0);
    }
    else
    {
        wait(NULL);
        return;
    }
}

例如,如果我要输入任何类型的函数,例如“ls”或“wc”,它会给我“错误:执行失败”消息,这意味着 fork() 没有正确运行。在我对 fork() 的理解中,这可能是一个小问题,但我完全被难住了。

这是我的整个程序:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>

char str[129];
enum {NOT_FOUND=0,FOUND};
enum {false=0,true};
static char *ptr;
const char *del;
int ReadLine(char *, int , FILE *);




char *mystrtok(char* string,const char *delim)
{
    int j,flag=NOT_FOUND;
    char *p;
    if(string != NULL)
    {
        ptr=string;
        p=string;
    }
    else
    {
        if(*ptr == '\0')
        return NULL;

        p=ptr;
    }

    while(*ptr != '\0')
    {
        del=delim;
        while(*del != '\0')
        {
            if(*ptr == *del)
            {
                if(ptr == p)
                {
                    p++;
                    ptr++;
                }
                else
                {
                    *ptr='\0';
                    ptr++;

                    return p;
                }
            }
            else
            {
                del++;
            }
        }
        ptr++;
    }
    return p;
}

void execute_func(char** tok)
{
    pid_t pid = fork();
    
    if (pid == -1)
    {
        printf("\nERROR: forking child process failed\n");
        return;
    }
    else if (pid == 0)
    {
        if (execvp(tok[0], tok) < 0)
        {
            printf("ERROR: exec failed\n");
        }
        exit(0);
    }
    else
    {
        wait(NULL);
        return;
    }
}
    


int main()
{
    int i;
    char *p_str,*token;
    char delim[10];
    delim[0] = ' ';
    delim[1] = '\t';
    delim[2] = '\n';
    delim[3] = '\0';
    char cwd[1024];
    char *tok[129];

    while(1)
    {
        tok[0] = NULL;
        fflush(stdin);
        fflush(stdout);
        printf("\n Enter a string to tokenize: ");
        //    printf("\n before scan");
        fflush(stdin);
        //    printf("\n fflush");
        ReadLine(str, 128, stdin);
        /*    scanf("%[^\n]",str); */
        printf("\n after scan");

        for (i = 1, p_str = str; ; i++, p_str = NULL)
        {
            token = mystrtok(p_str,delim);
            if (token == NULL)
            break;
            printf("%d: %s\n",i,token);
            tok[i-1] = token;
            printf("%s\n",tok[i-1]);
        }
        if(tok[0] != NULL)
        {
            if(strcmp(tok[0],"cd") == 0)
            {
                if (chdir(tok[1]) != 0)
                    perror("chdir() error()");

                getcwd(cwd, sizeof(cwd));
                printf("current working directory is: %s\n", cwd);
            }

            else if(strcmp(tok[0],"pwd") == 0)
                if (getcwd(cwd, sizeof(cwd)) == NULL)
                    perror("getcwd() error");
                else
                    printf("current working directory is: %s\n", cwd);

            else if(strcmp(tok[0],"exit") == 0)
                exit(3);

            else
            {
                execute_func(tok);
            }
        }
    }       
}


int ReadLine(char *buff, int size, FILE *fp)
{
    buff[0] = '\0';
    buff[size - 1] = '\0';             /* mark end of buffer */
    char *tmp;

    if (fgets(buff, size, fp) == NULL) 
    {
        *buff = '\0';                   /* EOF */
        return false;
    }
    else 
    {
        /* remove newline */
        if ((tmp = strrchr(buff, '\n')) != NULL) 
        {
            *tmp = '\0';
        }
    }
return true;
}

【问题讨论】:

  • 请提供complete minimal verifiable example。我们需要看看这个函数是如何被调用的。也许tok 没有正确的内容。另外,请致电perror 获取更具体的错误消息。
  • @kaylum 我在我的主函数中编辑了我正在调用的函数。
  • 请阅读链接。您提供的代码既不完整也不最小。如果您尝试创建一个最小示例,例如通过删除用户输入并对字符串进行硬编码,您甚至可以自己找到问题。
  • @kaylum 我不明白你为什么需要我的其余代码。我的问题在于函数本身,因为 fork() 命令没有按我的预期工作。
  • 你怎么知道的?根据定义,您在这里是因为您不知道问题出在哪里。该功能看起来是正确的。问题更可能在于token解析有问题。调试的输出是什么?如果在错误情况下调用perrror,它的输出是什么?

标签: c linux fork


【解决方案1】:

问题似乎在这里:

        if (token == NULL)
        break;
        printf("%d: %s\n",i,token);
        tok[i-1] = token;

尾随的NULL 永远不会在tok 中设置,从而导致execve 找不到列表的末尾。像这样应该可以解决它:

        tok[i-1] = token;
        if (token == NULL)
        break;
        printf("%d: %s\n",i,token);

【讨论】:

  • 这修复了它。谢谢你。大部分代码是教授给出的模板,也是其中的一部分。
猜你喜欢
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 2020-03-21
  • 1970-01-01
  • 1970-01-01
  • 2015-12-01
  • 2015-11-28
  • 1970-01-01
相关资源
最近更新 更多