Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C语言的背景工作(在玩具壳中实现)_C++_C_C++11 - Fatal编程技术网

C++ C语言的背景工作(在玩具壳中实现)

C++ C语言的背景工作(在玩具壳中实现),c++,c,c++11,C++,C,C++11,我想让它成为这样,当一个用户附加了一个命令后,它将在后台执行。出于某种原因,如果我正常执行命令,它会等待,如果我在后台执行命令,它会工作,但如果我正常执行命令,它不会等待。我肯定我只是做错了一些小事。任何想法: void executeSystemCommand(char *strippedCommand, char *background, int argc, char **args) { char pathToExecute[80]; // Check if comman

我想让它成为这样,当一个用户附加了一个命令后,它将在后台执行。出于某种原因,如果我正常执行命令,它会等待,如果我在后台执行命令,它会工作,但如果我正常执行命令,它不会等待。我肯定我只是做错了一些小事。任何想法:

void executeSystemCommand(char *strippedCommand, char *background, int argc, char **args) {
    char pathToExecute[80];


    // Check if command will be executed in the background
    int shellArgs;
    bool bg; 
    if (!strcmp(background, "-")) {
        bg = true;
        shellArgs = argc -1; 
    } else {
        bg = false;
        shellArgs = argc;
    }   

    // Save the linux commands in a new array
    char *executableCommands[shellArgs+1];
    int j;
    for (j = 0; j < shellArgs+1; j++) {
        executableCommands[j] = args[j];
    }   
    executableCommands[shellArgs] = NULL;

    // Check the $PATH
    const char delimiters[] = ":";
    char *token, *cp;
    char *forLater;
    int count = 0;
    char *path;
    path = getenv("PATH");

    // All of this just breaks up the path into separate strings
    cp = strdup(path);    
    forLater = strdup(path);
    token = strtok (cp, delimiters); 
    while ((token = strtok (NULL, delimiters)) != NULL) {
        count++;
    }   
    char **argv;
    int size = count+1;
    argv = (char**) malloc (size);
    count = 0;
    token = strtok (forLater, delimiters); 
    argv[0] = (char*) malloc (50);
    argv[0] = token;
    strcpy(argv[0],token);
    while ((token = strtok (NULL, delimiters)) != NULL) {
        count++;
        argv[count] = (char*) malloc (50);
        argv[count] = token;
    }   

    // This goes through the path to see if the linux command they entered
    // Ex: sleep exists in one of those files and saves it to a var
    int i;
    bool weHaveIt = false;
    int ac; 
    for (i = 0; i < count; i++) {
        char str[80];
        strcpy(str, argv[i]);
        strcat(str, "/");
        strcat(str, args[0]);
        ac = access(str, F_OK);
        if (ac == 0) {
            weHaveIt = true;
            strcpy(pathToExecute, str);
            break;
        }
    }

    if (!weHaveIt) {
        printf("That is not a valid command. SORRY!\n");
        return;
    }

    executableCommands[0] = pathToExecute;
    int status;

    // Get the array for 

    // If user wants command to be a background process
    if (bg) {
        int background_process_id;
        pid_t fork_return;
        fork_return = fork();

        if (fork_return == 0) {
            background_process_id = getpid();
            addJobToTable(strippedCommand, background_process_id);
            setpgid(0, 0);
            execve(executableCommands[0], executableCommands, NULL);
            exit(0);
        } else {
            return;
        }
    } else {
        int background_process_id;
        pid_t fork_return;
        fork_return = fork();

        if (fork_return == 0) {
            background_process_id = getpid();
            status = execve(executableCommands[0], executableCommands, NULL);
            exit(0);
        } else {
                wait(&status);
                return;
        }
    }
}
void executeSystemCommand(char*strippedCommand,char*background,int argc,char**args){
字符路径执行[80];
//检查命令是否将在后台执行
int shellArgs;
布尔bg;
如果(!strcmp(背景,“-”){
bg=真;
shellArgs=argc-1;
}否则{
bg=假;
shellArgs=argc;
}   
//将linux命令保存在新数组中
char*executableCommands[shellArgs+1];
int j;
对于(j=0;j
当父进程退出时,使用
fork()创建的每个子进程都将退出

if (fork_return == 0) {
   /* child process, do stuff */
} else {
   /* parent process, exit immediately */
   return;
}
解释 生成一个新进程作为当前进程(父进程)的子进程。每当类Unix操作系统中的进程终止时,其所有子进程也将终止。如果它们自己有子进程,那么它们也会被终止

解决方案 在大多数shell中,如果在行尾添加一个符号,则可以在后台启动进程:

myApplication arg1 arg2 arg3 ... argN &
我的应用程序arg1 arg2 arg3。。。argN&当父进程退出时,使用
fork()
创建的每个子进程都将退出

if (fork_return == 0) {
   /* child process, do stuff */
} else {
   /* parent process, exit immediately */
   return;
}
解释 生成一个新进程作为当前进程(父进程)的子进程。每当类Unix操作系统中的进程终止时,其所有子进程也将终止。如果它们自己有子进程,那么它们也会被终止

解决方案 在大多数shell中,如果在行尾添加一个符号,则可以在后台启动进程:

myApplication arg1 arg2 arg3 ... argN &
我的应用程序arg1 arg2 arg3。。。argN&为第三个作业调用
wait
会立即返回,因为第二个作业已完成,正在等待处理(也称为“僵尸”)。您可以检查
wait(&status)
的返回值,该值是已退出的进程的PID,并确保它是您正在等待的进程。如果不是,只需再次调用
等待

或者使用等待特定进程的
waitpid

/* Wait for child. was: wait(&status) */
waitpid(fork_return, &status, 0); 
如果这样做,您应该为
SIGCHLD
实现一个信号处理程序来处理已完成的后台作业,以防止“僵尸”子进程的累积

除此之外,在后台作业案例中,
fork()
的分支返回0您已经在新进程中,因此对
addJobToTable
的调用发生在错误的进程中。此外,还应检查所有调用的返回值;否则,有些事情可能会失败,而你却不知道。因此,在后台运行作业的代码应该更像这样:

    if (fork_return == 0) {
        setpgid(0, 0);
        if (execve(executableCommands[0], executableCommands, NULL) == -1) {
            perror("execve");
            exit(1);
        }
    } else if (fork_return != -1) {
        addJobToTable(strippedCommand, fork_return);
        return;
    } else {
        perror("fork"); /* fork failed */
        return;
    }

对第三个作业的
wait
调用会立即返回,因为第二个作业已完成,正在等待处理(也称为“僵尸”)。您可以检查
wait(&status)
的返回值,该值是已退出的进程的PID,并确保它是您正在等待的进程。如果不是,只需再次调用
等待

或者使用等待特定进程的
waitpid

/* Wait for child. was: wait(&status) */
waitpid(fork_return, &status, 0); 
如果你这样做,你应该