C - 打印后台子进程的退出状态,但返回父命令行访问权限

问题描述 投票:0回答:1

Hello in C 我想在子进程完成执行时打印其退出状态。我知道如何在前台进程中执行此操作(只需使用 waitpid),但在后台进程中,我希望在子进程分叉时立即向用户提供命令行访问权限。换句话说,我不能在父级的情况下等待,而是必须返回顶部并让 while 循环再次执行。我很欣赏一些见解。谢谢。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include <limits.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>

#define MAX_JOBS 100 //max jobs that can go on at once

pid_t jobs[MAX_JOBS];
int job_count = 0;
int last_exit_status = 0;
char* last_termination = 0;

void addJob(pid_t pid) {// Function to add a job to the list
   if (job_count < MAX_JOBS) {
       jobs[job_count] = pid;
       job_count++;
   }
}

//main func
int main() {
   int x = 0;
   char *token;
   char *argv[1024]; // Array to store command and arguments
   char *argvSec[1024];
   int i = 0;
   while(x == 0) {
       int pid = getpid();
       char* command = prompt();   //get user input
       if (command != NULL) {
           int childExitMethod;
           pid_t spwanPID = fork();

           switch (spwanPID){
           case -1:
               last_exit_status = 1;
           case 0:
               execvp(argv[0], argv);
               last_exit_status = 1;
               exit(1);
           default:
               if (isForeGround){
                   waitpid(spwanPID, &childExitMethod, 0); // Wait for the child only if foreground
                   if (WIFEXITED(childExitMethod) && !WEXITSTATUS(childExitMethod)) {
                       last_exit_status = 0;
                   } else {
                       printf("bash: %s: command not found\n", command);
                       last_exit_status = 1;
                   }
               } else if (isBackground){

               }
           }
       }
   }
   return 0;
}
c background fork parent-child
1个回答
0
投票

我遇到的问题是因为 waitpid(spwanPID, &childExitMethod, 0); 阻塞并等待子进程完成运行,因此我无法在分叉后立即给予用户命令行访问权限。我可以通过使用 waitpid(-1, ¤tStatus, WNOHANG); 来解决这个问题,其中 WHOHANG 阻止 waitpid 阻塞。我可以通过在提示功能之前执行此操作来检查子终止。这是一个例子。

void check_background() {
    if (backgroundChildrenRunning > 0) {        //this function is to print the background process termination signal
        int currentStatus;
        int completedChild = waitpid(-1, &currentStatus, WNOHANG);      //use WHOHANG so it does not block

        if (completedChild > 0) {
            if (WIFEXITED(currentStatus)) {
                printf("Background process with ID %d has been completed. Exit value: %d.\n", completedChild, WEXITSTATUS(currentStatus));
                last_termination = WEXITSTATUS(currentStatus);
            }
            else {
                if (completedChild == backgroundPid) {
                    printf("Background process with ID %d has been completed. Terminated by signal: %d.\n", completedChild, WTERMSIG(currentStatus));
                    last_termination = WTERMSIG(currentStatus);
                }
            }
            backgroundPid = 0;
            backgroundChildrenRunning -= 1;
        }
    }
}


int main() {
    int x = 0;
    char *token;
    char *argv[1024]; 
    char *argvSec[1024];

    while(x == 0) {
        check_background();     //check background here
        int pid = getpid();
        char* command = prompt(pid);   //get user input
        if (command != NULL) {
            int childExitMethod;
            pid_t spwanPID = fork();

            switch (spwanPID){
            case -1:
                last_exit_status = 1;
            case 0:
                execvp(argv[0], argv);
                last_exit_status = 1;
                exit(1);
            
            default:
                if (hasSymbolEnd == 0){
                    waitpid(spwanPID, &childExitMethod, 0); // Wait for the child only if background
                    if (WIFEXITED(childExitMethod) && !WEXITSTATUS(childExitMethod)) {
                        last_exit_status = 0;
                    } 
                } else {
                    printf("background pid is %d\n", spwanPID);      //print the child pid as requeste
                    backgroundChildrenRunning += 1;
                }
            }
        }
    }
    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.