C fork()导致未指定的意外函数调用

C fork()导致未指定的意外函数调用,c,linux,shell,fork,system-calls,C,Linux,Shell,Fork,System Calls,我的第一篇堆栈溢出帖子,我是网站上的一个潜伏者,但我真的想开始问一些我自己的问题 我正在使用unistd.h库学习fork系统调用。我想测试一下我在学什么。我已经按照一本教科书上的例子介绍了在UNIX中创建一个简单的进程。我在OSX上做这个。我已经被设置了一个创建shell的任务,我不想得到构建shell的完整答案,因此我要问的是这个特定的系统调用,而不是整个程序 代码本身运行完全正常,并给出了预期的输出 这是工作正常的代码: #include <stdio.h> #include

我的第一篇堆栈溢出帖子,我是网站上的一个潜伏者,但我真的想开始问一些我自己的问题

我正在使用unistd.h库学习fork系统调用。我想测试一下我在学什么。我已经按照一本教科书上的例子介绍了在UNIX中创建一个简单的进程。我在OSX上做这个。我已经被设置了一个创建shell的任务,我不想得到构建shell的完整答案,因此我要问的是这个特定的系统调用,而不是整个程序

代码本身运行完全正常,并给出了预期的输出

这是工作正常的代码:

#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid;
    pid = fork();
    if(pid == 0){
        printf("\nI'm the child\n\n");
    }
    else if(pid > 0){
        printf("\nI'm the parent, child has pid: [%d]\n", pid);
    }
    else{
        printf("ERROR");
    }
    return 0;
}
壳牌公司

壳牌公司


任何帮助都将不胜感激,谢谢

您正在创建的孩子将像他的父亲一样循环,并且您将让每个循环都有一个新的过程。 fork:创建精确的进程映像

您可以做的是: 加入孩子(父亲等待孩子完成)


2-或仅在printfChild之后添加一个出口\n;这将结束子循环,并保持父循环运行。

您正在创建的子循环将像其父循环一样,并且您将使每个循环都有一个新的进程。 fork:创建精确的进程映像

您可以做的是: 加入孩子(父亲等待孩子完成)


2-或仅在printfChild之后添加一个出口\n;这将结束子进程,并保持父进程运行。

使用fork创建新进程时,子进程将从fork的点继续。所以,您的孩子打印孩子,但它从测试返回。因此,它将继续运行只应运行父级的代码

您在较小的代码段中看不到这一点,因为您立即从main返回,导致子进程退出

您需要在完成其部分后让子项退出。此外,父进程应该等待子进程,这样就不会留下僵尸进程

void test(){
    pid_t pid;
    pid = fork();
    if(pid == 0){
        printf("Child\n");
        _exit(0);    // exit child; use _exit instead of exit 
                     //to prevent atexit handlers from being called
    }
    else if(pid > 0){
        printf("I'm the parent, child has pid %d\n", pid);
        // wait for child to finish
        wait(NULL);
    }
    else{
        printf("ERROR");
    }
}

另外,在shellLoop中,在屏蔽库函数exit时,将变量exit重命名为其他名称。

使用fork创建新进程时,子进程将从fork点继续。所以,您的孩子打印孩子,但它从测试返回。因此,它将继续运行只应运行父级的代码

您在较小的代码段中看不到这一点,因为您立即从main返回,导致子进程退出

您需要在完成其部分后让子项退出。此外,父进程应该等待子进程,这样就不会留下僵尸进程

void test(){
    pid_t pid;
    pid = fork();
    if(pid == 0){
        printf("Child\n");
        _exit(0);    // exit child; use _exit instead of exit 
                     //to prevent atexit handlers from being called
    }
    else if(pid > 0){
        printf("I'm the parent, child has pid %d\n", pid);
        // wait for child to finish
        wait(NULL);
    }
    else{
        printf("ERROR");
    }
}

此外,在shellLoop中,在屏蔽库函数出口时,将变量exit重命名为其他名称。

这不是一个分叉炸弹,只是一个bug。子进程应在完成时退出。即,在if pid==0块内。最终,分叉过程应该终止。据我所见,家长没有理由关心它是否/何时这样做,但它仍然应该这样做,否则它也会在其过程中返回到命令解释器和选择菜单。您的孩子和家长都会返回到您的循环。两个出口都没有。现在,你有两个过程。当您在stdin中输入某个内容时,它将传递给孩子。但如果子级退出,则父级仍在运行,等待从stdin读取。如果您多次运行测试,您将有多个实例等待输入。我没有看到一个循环创建了一个炸弹虽然…有一个缓冲区溢出在这段代码中。您应该将scanf%s、&command替换为scanf%80s、&command,或者改用fgets。@DavidConrad-除非有人键入很长的字符串,否则我看不出这会导致缓冲区溢出。不过,防范这种情况是一种很好的做法。缓冲区溢出意味着缓冲区溢出……这不是一个分叉炸弹,只是一个bug。子进程应在完成时退出。即,在if pid==0块内。最终,分叉过程应该终止。据我所见,家长没有理由关心它是否/何时这样做,但它仍然应该这样做,否则它也会在其过程中返回到命令解释器和选择菜单。您的孩子和家长都会返回到您的循环。两个出口都没有。现在,你有两个过程。当您在stdin中输入某个内容时,它将传递给孩子。但如果子级退出,则父级仍在运行,等待从stdin读取。如果您多次运行测试,您将有多个实例等待输入。我没有看到一个循环创建了一个炸弹虽然…有一个缓冲区溢出在这段代码中。您应该将scanf%s、&command替换为scanf%80s、&command,或者改用fgets。@DavidConrad-除非有人键入很长的字符串,否则我看不出这会导致缓冲区溢出。这是一个很好的做法来防止这种情况。缓冲区溢出意味着缓冲区溢出…谢谢,这解决了问题。当我试着恢复时,我的电脑不再坏了
取消程序后,waitNULL也允许继续执行,否则它会中断。感谢关于exit变量的提示,我在阅读本书时很快写了这篇文章,我将完全重写这篇文章,我看到很多人使用状态变量来处理这类程序。谢谢,这解决了问题。当我尝试运行程序时,我的计算机不再崩溃,waitNULL也允许继续执行,否则它会崩溃。同样感谢关于exit变量的提示,我在读这本书时快速写下了这篇文章,我将完全重写它,我见过很多人在这类程序中使用状态变量。谢谢。我知道它们都将从创建子对象的时候开始运行,但是循环不应该再次调用测试函数,除非“test”作为命令输入,因为某种原因,它正在循环并再次启动该函数。谢谢。我知道它们都将从创建子对象的点开始运行,但是循环不应该再次调用测试函数,除非“test”作为命令输入,因为某种原因,它正在循环并再次启动该函数。
#define MAX_STRING_LEN 80

#define clear() printf("\033[H\033[J") /* Terminal escape codes for clearing the console */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

void shellLoop();
int commandInterpreter(char * cmd);
void info();
void test();
void shellMessage(char * message);
void test(){
    pid_t pid;
    pid = fork();
    if(pid == 0){
        printf("Child\n");
        _exit(0);    // exit child; use _exit instead of exit 
                     //to prevent atexit handlers from being called
    }
    else if(pid > 0){
        printf("I'm the parent, child has pid %d\n", pid);
        // wait for child to finish
        wait(NULL);
    }
    else{
        printf("ERROR");
    }
}