myshell:儿童流程不在后台运行

发布于 2025-01-21 00:58:37 字数 3925 浏览 4 评论 0原文

我正在编写我的shell程序。

它应该支持管道处理。它还应该识别“&”在命令末尾并在后台运行子进程(如果有“&”)已附。

我的程序的问题是, ls | grep txt 效果很好,但是 ls | greptxt & 不起作用。

为此,我在全局声明了 pid 数组,用于存储生成的子进程的 ID,以及 reaped_id 数组,用于存储已获取的子进程的 ID。

如果第一个子进程尚未被重新获取,则第二个进程将被阻止(sigsuspended)。此外,当第一个进程结束时,如果第二个进程当时已创建,则 sigchld 处理程序会向第二个进程发送 SIGCONT 信号。

Sigchld 处理程序中的调试结果:即使在第二个进程被阻塞后,它也不向第二个进程发送 SIGCONT 信号。

更具体地说,父进程中的增量 pcount(创建的子进程数)不反映在 Sigchld 处理程序中。(全局定义)这是我的 shell 的一部分。

       while(buffer[idx] != '\0'){
                
            /*check if it is piped process*/
            pipe_start_flag = pipe_end_flag;  // if last process was piping process, then this process is a piped process

            parse_line(&buffer[idx], argv, &idx, &pipe_end_flag); // parse until it meets '\0' or '|'(assign its (index-1) on idx)

            pid[pcount] = Fork(); 
            if(pid[pcount] == 0){
                int big_bro_idx = pcount - 1; // index of last process
                if(!pipe_start_flag && pipe_end_flag){
                    dup2(fd[WRITEEND],STDOUT_FILENO); 
                    close(fd[READEND]); 
                }
                else if(pipe_start_flag && !pipe_end_flag){
                    dup2(fd[READEND], STDIN_FILENO);
                    close(fd[WRITEEND]);  
                    write(STDOUT_FILENO, "second process spawned\n", 23); // debugger 


                    while(reaped_id[big_bro_idx] == 0){ // while last process are executing. If last process terminate, this will be its pid  
                        write(STDOUT_FILENO, "this line works\n", 15); // debugger code 
                        Sigsuspend(&blocking_mask);
                    }
                }   
                if(execvp(argv[0], argv) < 0){
                    printf("%s: command not found\n", argv[0]);
                    exit(1);              
                }    
            }
            
            else{ // parent process"
                close(fd[WRITEEND]); 
                if(!bg){
 
                    while(reaped_id[pcount] <= 0 && sigtstp_flag == false){
                        Sigsuspend(&blocking_mask); // wait for sigchld 
                    }
                    sigtstp_flag = false; // reset flag to false(it changed at sigtstp_flag)
                }
                else; // background process
                    
                write(STDOUT_FILENO, "pcount increased\n", 17); // debugging code 
                ++pcount; 
            }
        
            ++idx; 
        }

接下来是我的 SIGCHLD 处理程序。

void sigchld_handler(int sig){
     sigset_t mask, prev; 
     int status; 
     int olderrno = errno; 


    Sigfillset(&mask); 
    Sigprocmask(SIG_BLOCK, &mask, &prev); 

    while((reaped_id[reap_count] = waitpid(-1, &status, WNOHANG)) > 0)
    {
        write(STDOUT_FILENO, "process terminated\n", 19); 
        reap_count ++; 
    }
    
    printf("%d %d %d %d ", pid[reap_count], reap_count, pcount, reaped_id[reap_count -1]); 
    if(pid[reap_count] > 0 || WIFSTOPPED(status)){ // if there is little brother process 
        Kill(pid[reap_count], SIGCONT);  // send SIGCONT singal to blocked sibling process 
        write(STDOUT_FILENO, "I alarmed my sibling", 20); // debuggging code; not executed
    }

    Sigprocmask(SIG_SETMASK, &prev, NULL); 
    errno = olderrno; 
}

输入图片这里的描述

流程图:

  1. Shell 生成两个子进程
  2. 第二个进程被阻塞,因为第一个进程未完成
  3. 第一个进程终止的
  4. Sigcont 信号应该从 Sigchld 处理程序发送到第二个进程,但没有。 (它显示 pcount 增加了,但是当我在 sigchld 处理程序中打印 pcount 时,它根本没有增加。)

我整夜没睡这个问题。如果您需要完整的代码来执行,我们会将其发送给您。

如果有什么需要补充的请告诉我,我会立即补充。

I'm writing myshell program.

it should supportpipe processing. It should also recognize the '&' at the end of the command and run the child process in the background if the '&' is attached.

The problem with my program is,
ls | grep txt works well, but ls | greptxt & is not working.

To this end, I declared globally the pid array that stores the IDs of the generated child processes and the reaped_id array that stores the IDs of the reaped child processes.

The second process are blocked(sigsuspended) if the first child process had not been reapped. Also, when the first process ends, sigchld handler sends a SIGCONT signal to the second process if the second process has been created that moment.

Debugging results in Sigchld handler: it does not send SIGCONT signals to the second process even after the second process has been blocked

More specifically, the incremental pcount (number of child processes created) in the parent process is not reflected in the Sigchld handler.(globally defined) Here's a part of my shell.

       while(buffer[idx] != '\0'){
                
            /*check if it is piped process*/
            pipe_start_flag = pipe_end_flag;  // if last process was piping process, then this process is a piped process

            parse_line(&buffer[idx], argv, &idx, &pipe_end_flag); // parse until it meets '\0' or '|'(assign its (index-1) on idx)

            pid[pcount] = Fork(); 
            if(pid[pcount] == 0){
                int big_bro_idx = pcount - 1; // index of last process
                if(!pipe_start_flag && pipe_end_flag){
                    dup2(fd[WRITEEND],STDOUT_FILENO); 
                    close(fd[READEND]); 
                }
                else if(pipe_start_flag && !pipe_end_flag){
                    dup2(fd[READEND], STDIN_FILENO);
                    close(fd[WRITEEND]);  
                    write(STDOUT_FILENO, "second process spawned\n", 23); // debugger 


                    while(reaped_id[big_bro_idx] == 0){ // while last process are executing. If last process terminate, this will be its pid  
                        write(STDOUT_FILENO, "this line works\n", 15); // debugger code 
                        Sigsuspend(&blocking_mask);
                    }
                }   
                if(execvp(argv[0], argv) < 0){
                    printf("%s: command not found\n", argv[0]);
                    exit(1);              
                }    
            }
            
            else{ // parent process"
                close(fd[WRITEEND]); 
                if(!bg){
 
                    while(reaped_id[pcount] <= 0 && sigtstp_flag == false){
                        Sigsuspend(&blocking_mask); // wait for sigchld 
                    }
                    sigtstp_flag = false; // reset flag to false(it changed at sigtstp_flag)
                }
                else; // background process
                    
                write(STDOUT_FILENO, "pcount increased\n", 17); // debugging code 
                ++pcount; 
            }
        
            ++idx; 
        }

Next is my SIGCHLD handler.

void sigchld_handler(int sig){
     sigset_t mask, prev; 
     int status; 
     int olderrno = errno; 


    Sigfillset(&mask); 
    Sigprocmask(SIG_BLOCK, &mask, &prev); 

    while((reaped_id[reap_count] = waitpid(-1, &status, WNOHANG)) > 0)
    {
        write(STDOUT_FILENO, "process terminated\n", 19); 
        reap_count ++; 
    }
    
    printf("%d %d %d %d ", pid[reap_count], reap_count, pcount, reaped_id[reap_count -1]); 
    if(pid[reap_count] > 0 || WIFSTOPPED(status)){ // if there is little brother process 
        Kill(pid[reap_count], SIGCONT);  // send SIGCONT singal to blocked sibling process 
        write(STDOUT_FILENO, "I alarmed my sibling", 20); // debuggging code; not executed
    }

    Sigprocmask(SIG_SETMASK, &prev, NULL); 
    errno = olderrno; 
}

enter image description here

process graph:

  1. Shell spawn both child processes
  2. The second process is blocked because the first process is not finished
  3. First process terminated
  4. Sigcont signal should be sent from Sigchld handler to second process but not.
    (It shows that the pcount is increased, but when I print a pcount in sigchld handler, it doesn't increase at all.)

I've been up all night for this problem. If you need a full code to execute, we will send it to you.

If there is anything I need to supplement, please tell me and I will supplement it right away.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文