C++ 如何使子进程在完成后立即返回以运行父进程(当我们执行fork时)?

C++ 如何使子进程在完成后立即返回以运行父进程(当我们执行fork时)?,c++,fork,C++,Fork,我编写了一个模拟cp函数(在bash中复制)的函数,基本上该函数将一个文件作为输入,并将其复制到dest文件: cp sourceFile destFile . 如果行尾有一个“&”,cp函数可以在前端或后端运行(cp sourceFile destFile&) 为了支持这一点,我使用了fork,儿子基本上复制了文件,他父亲如果命令是fore ground,他会等待孩子,否则如果命令是back ground,我们就不会等待(我们将它添加到特定列表中) 我的问题是,在son完成代码退出后,如果命

我编写了一个模拟cp函数(在bash中复制)的函数,基本上该函数将一个文件作为输入,并将其复制到dest文件:

cp sourceFile destFile .
如果行尾有一个“&”,cp函数可以在前端或后端运行(
cp sourceFile destFile&

为了支持这一点,我使用了fork,儿子基本上复制了文件,他父亲如果命令是fore ground,他会等待孩子,否则如果命令是back ground,我们就不会等待(我们将它添加到特定列表中)

我的问题是,在son完成代码退出后,如果命令在前台运行,cp函数将返回,但当它退出cp函数时,它会打印一些内容,我不希望发生这种情况:(

(最后举例)

我的职能:

void CopyCommand::execute() {
    char *buff = new char[1024]();
    int fdRead = open(args[1], O_RDONLY);
    if (fdRead == -1) {
        perror("smash error: open failed");
        return;
    }

    int fdWrite = open(args[2], O_WRONLY | O_TRUNC);
    if (fdWrite ==-1) {              
        fdWrite = open(args[2], O_WRONLY | O_CREAT, 0666);
        if (fdWrite == -1) {
            perror("smash error: open failed");
            return;
        }
    }

    PID = fork();
    if (PID == 0) {
        setpgrp();
        int count = read(fdRead, buff, 1);  /// read from the file fd1 into fd2
        while (count != -1) {
            if (!count) {
                break;
            }
            if (write(fdWrite, buff, 1) == -1) {
                perror("smash error: write failed");
                return;  // not sure if we should return
            }
            count = read(fdRead, buff, 1);
            if (count == -1) {
                perror("smash error: read failed");
                return;
            }
        }
        return ;
    }  if (PID > 0) { // if i am the father then i will :
        if (isBackground) {
            // if cp command is running in the background then add it to the jobs list
            SmallShell::getInstance().SmallShellGetJobs()->removeFinishedJobs();
            SmallShell::getInstance().Jobs_List.addJob(SmallShell::getInstance().currentCommand, false);
            cout << "smash: " << args[1] << " was copied to " << args[2] << endl;
            return;
        } else {
            int status;
            waitpid(PID, &status, WUNTRACED);
            cout << "smash: " << args[1] << " was copied to " << args[2] << endl;
            return;
        }
    } else {
        perror("smash error: fork failed");
    }
}
产出将是:

outside of cp function :(
smash: test_src_1.txt was copied to test_newdest_1.txt

fork
的工作方式与您想象的不同。子进程在终止之前一直存在,并继承父进程的调用堆栈等内容;当您在子进程中
return
时,您只需转到调用函数

您需要使用
exit
或同一系列中的某些功能。例如:

if (PID == 0) {
        setpgrp();
        int count = read(fdRead, buff, 1);  /// read from the file fd1 into fd2
        while (count != -1) {
            if (!count) {
                break;
            }
            if (write(fdWrite, buff, 1) == -1) {
                perror("smash error: write failed");
                exit(0);  // not sure if we should return
            }
            count = read(fdRead, buff, 1);
            if (count == -1) {
                perror("smash error: read failed");
                exit(1);
            }
        }
        exit(1) ;
    }

请注意,这是在bash中添加
&
时的行为(只需尝试
回显测试&
)。显示的代码存在可怕的内存泄漏。您能否解释一下,您希望通过手动
new
ing一个缓冲区而不是使用
std::vector
为您管理此分配来完成什么,对吗?现在您必须记住始终
删除它。似乎您从未在任何地方执行过。您为什么决定
新的
缓冲区,迫使你自己去处理额外的开销,无论你从这个函数返回到哪里,你都要记住它来删除它,而你从来没有这样做过。使用
std::vector
并让它去做这些事情,这对你来说不是更有意义吗?但是我没有把&放在最前面我要测试的行结束测试确定我要将其更改为vector,但这不是我现在的主要问题!我的问题是为什么在子复制完文件后,它会从函数中返回并打印一些内容,然后返回以运行父进程??“父/子”,而不是“父/子”退出基本上结束了子进程?返回到父进程?它实际上起了作用我很高兴!!!谢谢
exit
终止当前进程。没有任何“返回到父进程”,因为父进程仍然独立运行(尽管您使用
waitpid
)进行阻止。这确实很有帮助!谢谢:)
if (PID == 0) {
        setpgrp();
        int count = read(fdRead, buff, 1);  /// read from the file fd1 into fd2
        while (count != -1) {
            if (!count) {
                break;
            }
            if (write(fdWrite, buff, 1) == -1) {
                perror("smash error: write failed");
                exit(0);  // not sure if we should return
            }
            count = read(fdRead, buff, 1);
            if (count == -1) {
                perror("smash error: read failed");
                exit(1);
            }
        }
        exit(1) ;
    }