首页 > 解决方案 > 当孩子收到 sigstop 信号时读取函数的行为

问题描述

节目说明

这些程序会产生 n 个子进程,这些子进程在创建后立即暂停。之后,这些子进程轮流通过管道与父进程对话。

他们谈话的时间是固定的(例如:应该总共谈话 20 次,但当他们连续谈话 7 次时停止并进入下一个流程)

程序流程

  1. 分叉所有的孩子
  2. 在创建后立即暂停它们
  3. 通过发送信号唤醒他们
  4. 子级通过管道向父级写入(在固定的时间内),然后在向父级发送信号后立即停止/父级读取管道的内容并写入 STDOUT
  5. 当父母收到信号改变管道读取其他孩子和信号唤醒下面的孩子

问题

我面临的问题是,当是时候过渡到下一个进程以收听它时,即使我确实在子进程中的管道。阅读时我是否缺少关于 SIGSTOP 和 SIGCONT 的内容。

注意:我确实阅读了文档

程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <signal.h>

#define LOOP_SIZE 20;

/* SIG HANDLERS DEFINITION */
void parentsighandler(int);

/* GLOBAL VARIABLE DEFINITION */ 
pid_t n, ppid, wpid;
int nb_args,  read_return;

// array of pid_t to send signals to child
pid_t  *child_pids;     

volatile sig_atomic_t status = 0;
volatile sig_atomic_t compteur = 0;

int main(int argc, char *argv[]){   
    write(STDERR_FILENO, "** Begining the program\n", 24); // debug
    nb_args = argc - 1; 
    if (nb_args >= 1 ){
        // Variable initialisation
        child_pids= malloc(nb_args * sizeof(pid_t)); 

        // String for sprintf
        char sstr[40]; 
        char rstr[40];
        char pidstr[23];
        char strichild[16];
        char strloopchild[10];

        // Initializing all the pipes for the processes
        int p[2 * nb_args];  

        // getting the pid of the parent process
        ppid = getpid();
        sprintf(pidstr, "Pid of parent is : %d\n", ppid);
        write(STDERR_FILENO, pidstr, 23); // debug

        int i, j, stop_val;

        //Initializing all pipes
        write(STDERR_FILENO, "**Init pipes\n", 13); // debug
        for (i = 0; i < nb_args; i++){
            if (pipe(&p[2*i]) == -1){
                perror("Error : pipe failed");
                _exit(EXIT_FAILURE);
            }
        }
        write(STDERR_FILENO, "**end init pipes\n", 17); // debug
        write(STDERR_FILENO, "**Begin fork\n", 15); // debug 
        for (i = 0; i <  nb_args; i ++){
            switch( n = fork()){
            case -1:
                perror("Error : fork failed");
                _exit(EXIT_FAILURE);
            case 0:
                /* CHILD */
                sprintf(strichild, "**In child n%d\n", i); // debug
                write(STDERR_FILENO, strichild, strlen(strichild)); // debug
                if (0 == (stop_val = atoi(argv[i+1]))){
                    perror("atoi failed");
                    _exit(EXIT_FAILURE);
                }
                sprintf(strichild, "stop_val is : %d\n", stop_val); // debug
                write(STDERR_FILENO, strichild, strlen(strichild)); // debug
                close(p[i*2]);
                for (j = 1; j <= 20 ; j++){
                    sprintf(strloopchild, "loop : %d\n", j); // debug
                    write(STDERR_FILENO, strloopchild , strlen(strloopchild)); // debug
                    if (j % stop_val == 0){
                        write(STDERR_FILENO, "I am  paused\n", 15); // debug
                        if ( kill(ppid, SIGUSR1) == -1){
                            write(STDERR_FILENO, "Could not kill\n",15); // debug
                        }
                        write(STDERR_FILENO, "Sent a sigusr1\n",15); // debug
                        kill(getpid(), SIGSTOP);

                    } 
                    write(STDERR_FILENO, "In child : ",11);  
                    sprintf(sstr, "J ecris sur l'entree %d du pipe\n", i*2+1);  
                    write(STDERR_FILENO, sstr, strlen(sstr));
                    sprintf(sstr, "Je suis le proc %d : message %d\n", getpid(), j);
                    write(STDERR_FILENO, sstr, 40); // debug
                    write(p[i * 2 + 1], sstr, 40);
                    sleep(1);

                }   
                close(p[i*2+1]);
                write(STDERR_FILENO, "**Exiting the child\n", 20); // debug
                _exit(EXIT_SUCCESS);

            default:
                /* PARENT - process scheduling */
                write(STDERR_FILENO, "**Parent - puting to sleep childs\n", 34); // debug 
                child_pids[i] = n;
                kill(n, SIGSTOP);
                // Setting up the signal
                signal(SIGUSR1, parentsighandler); 
            } 
        }
        write(STDOUT_FILENO, "Debut de l'ordonnancement\n",26);
        char strpids[20];
        for (i = 0; i < nb_args; i++){
            sprintf(strpids, "id processus : %d\n", child_pids[i]);
            write(STDOUT_FILENO, strpids, 20);
        }
        char mystr[17];
        sprintf(mystr, "compteur : %d\n", compteur); // debug
        write(STDOUT_FILENO, mystr, 17); // debug  
        kill(child_pids[compteur], SIGCONT);
        while(1){
            if (read(p[2 * compteur], rstr, 40) > 0) {
                write(STDOUT_FILENO,"P : ",5);
                write(STDOUT_FILENO, rstr, 40);
                sprintf(mystr, "compt value: %d\n", compteur); // debug
                write(STDOUT_FILENO, mystr, 17); // debug 
            } else {
                write(STDERR_FILENO, "Erreur lecture\n", 15);
            } 
            sleep(1);
        }


    } else {
        perror("Error : Not enough args\n");
        _exit(EXIT_FAILURE);
    }   
    return 0;
}

void parentsighandler(int sig){
    if (sig == SIGUSR1){
        write(STDOUT_FILENO, "*************\n", 14);//debug
        write(STDOUT_FILENO, "P : going into sig handler\n", 28); // debug
        if (compteur == (nb_args - 1)){
            compteur = 0;   
        } else {
            compteur ++;
        }
        kill(child_pids[compteur], SIGCONT);

        char strst[19];
        sprintf(strst, "P : compteur : %d\n", compteur); // debug
        write(STDOUT_FILENO, strst, 19); // debug 
        write(STDOUT_FILENO, "*************\n", 14);//debug
    }
}

标签: cunixprocessforksystem

解决方案


推荐阅读