孩子收到sigstop信号时的读取功能行为

时间:2019-01-03 20:15:54

标签: c unix process fork system

程序说明

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

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

程序流程

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

问题

我面临的问题是,当需要过渡到下一个进程进行收听时,即使我确实在write-上进行写操作,我也不会从下一个孩子的管道中得到任何东西子进程中管道的末端。阅读时我对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
    }
}

0 个答案:

没有答案