【问题标题】:fork() and Execve, minix system C, core dumpsfork() 和 Execve、minix 系统 C、核心转储
【发布时间】:2015-11-05 22:34:44
【问题描述】:

我现在正在学习 C,并负责在 Minix 虚拟机中创建一个 shell,我正在使用 Minix 中已有的库函数来完成这项工作,例如 ls、cd 等。 ..

我遇到了一个问题,在 fork 子进程后,我导致核心转储,而不是执行我的命令

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

    /*Initialise variables*/
    int pid;
    char *envp[] = { NULL };
    char userInput[256];

void isParent(){
    int stat;
    waitpid(-1, &stat, 0);
}

int main(int argc, char *argv[]) {

    /*Infinite loop to cause shell to be "permenant"*/
    while(1){
        /*"*" to lead every line*/
        printf("%s","*");
        /*Get user input*/
        scanf("%s", userInput); 
        /*Leave an exit clause, to not be permenantly stuck in loop*/
        if(strcmp(userInput, "exit") == 0){
            exit(1);
        }
        /*create my child process*/
        pid = fork(); 

        /*if process is parent, wait*/
        if (pid != 0){
        isParent(); 
        }
        /*Perform function typed by the user*/
        execve(userInput, &argv[1], envp);          
    }
}

这是我目前正在使用的代码,当将 /bin/ls 作为我的 shell 的参数传递时,我可以让它在一个用户输入中打印 ls,两次,但是它在执行时退出 shell采取行动,这是不应该的。我希望能够使用其他功能,让它们打印一次,然后返回等待用户输入。

当不传递参数时,shell 将只接受“退出”,不接受其他命令。如果我从我的主方法、execve 或两者中删除参数子句 (argv[]),它们会引发错误,这是您所期望的。

我已经阅读了有关我使用过的所有功能的文档,并专门选择了它们,因此我希望不必更改它们,除非我正在做的事情实际上无法使用它们。

仍在学习 C,因此我希望使用更小的技术术语或更易于理解的短语。我不确定我的问题之前是否曾提出过问题,但我已经用大约 20 种不同的方式搜索了我的问题,并且我的问题的大多数版本都是为 c++、c# 编写的,或者与我的不相似问题,据我了解。

我还要待几个小时,所以如果我错过了任何信息,请随时发表评论并要求澄清、信息或其他任何事情。

【问题讨论】:

  • isParent() 返回时你认为会发生什么?如果没有else,它将运行evecve(),它永远不会返回。
  • @EOF 我希望isParent() 陷入无限循环,这样我的 shell 可以在孩子为我执行我的功能时继续运行,然后一旦孩子完成了它的事情,就可以返回 shell 执行另一个功能。
  • 在检查命令行参数时,永远不要访问argv[0]以外的地方,直到检查argc以确保命令行参数确实存在。访问不存在的参数将导致通过 NULL 指针访问的段错误或访问某些随机区域。无论哪种情况,结果都是未定义的行为。 IE。在访问 argv[] 之前检查 argc
  • 这条线:scanf("%s", userInput); 有几个问题:1) 始终检查返回值(而不是参数值)以确保操作成功。 2) 格式说明符%s 没有大小限制,因此用户很容易超出输入缓冲区userInput[]。为避免此问题,请在 %s 格式说明符上放置一个最大长度修饰符,该修饰符比输入缓冲区的长度小一。 (请记住,带有 %s 的 scanf() 总是在缓冲区末尾附加一个 NUL 字节)在这种情况下,建议:`scanf("%255s", userInput);
  • fork() 函数可以有以下三种返回指示中的任何一种:>0 表示在父项中 ==0 表示在子项中,pid = fork(); if( pid ==0 ) { // then child execve(); perror( "exeve() failed"); exit( EXIT_FAILURE )' } else if( pid > 0 ) { then parent ... } else { // fork() failed perror( "fork() failed" ); exit( EXIT_FAILURE ); }

标签: c shell minix execve


【解决方案1】:

变化:

    /*if process is parent, wait*/
    if (pid != 0){
    isParent(); 
    }
    /*Perform function typed by the user*/
    execve(userInput, &argv[1], envp);

到:

    /*if process is parent, wait*/
    if (pid != 0){
    isParent(); 
    }
    else
    {
    /*Perform function typed by the user*/
    execve(userInput, &argv[1], envp);
    _exit(0); /* just in case */
    }

【讨论】:

  • ...“以防万一”,您明确的意思是“以防 execve() 失败”,对吧?
  • @BenBowen:你确实意识到waitpid()最终应该返回?
  • @BenBowen "escape" 什么
  • @BenBowen:哦,等等。不要告诉我你认为isParent() 不能return,因为它没有以return-statement 结尾?
  • @BenBowen: waitpid() 在孩子退出时返回。当您execve()d 的程序终止时,孩子退出。你以前肯定写过一些程序吗?你会注意到大多数有用的程序最终都会终止......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-19
  • 2018-07-10
  • 2013-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多