Хранить данные в программе дочернего процесса на языке Си

#c

#c

Вопрос:

Я хочу создать программу, которая подсчитывает количество символов в тексте, для этого я хочу, чтобы моя программа работала со связью родительского / дочернего процессов, идея проста: я хочу, чтобы родитель прочитал стандартный идентификатор и отправил символы дочернему элементу, который будет считать и возвращать результат.

Я хочу вернуть результат после прочтения всего текста, тогда родительский файл отобразит результат следующим образом: для такого текста, как этот «АаааА», я получаю:

  • ‘a’ отображается 3 раза

  • ‘A’ отображается 2 раза

Для выполнения моей задачи я использовал каналы for и 2 вот пример моего кода :


 // I'll skip the code for variable and file input because i have a specific question.
.......
 // basic code

if( pid_child == 0){

 // child code

    close(pipe_1[1]);
    close(pipe_2[0]);

    read(pipe_1[0], amp;caract, sizeof(char));

}else {
   // parent area
    while((c = fgetc(file)) != EOF){
        if((c >= 'A' amp;amp; c <= 'Z') || (c >= 'a' amp;amp; c <= 'z')){

             close(pipe_1[0]);
             close(pipe_2[1]);

             write(pipe_1[1], amp;c, sizeof(char));
        } 
    }
 }
  

Я знаю, что когда вы fork() являетесь родительским процессом, вы создаете копию этого процесса, и я хочу знать, как мне сохранить весь результат в дочернем процессе, тогда я бы прочитал их или вызвал их в конце чтения моего файла?

Например, я хочу создать 2D динамический массив, который может содержать все символы, если первое измерение и количество встречаемости во втором измерении.

Для предыдущего примера я бы

int **array;
array = malloc(2 * sizeof(int *));

и это дало бы мне :

A 2

a 3

Я знаю, как общаться между дочерним и родительским процессами назад и в-четвертых, но моя проблема в том, что я хочу абсолютно точно вызвать конечный продукт этого массива после прочтения всего моего текста, чтобы родитель не мог получить результат до этого?

Есть ли способ сделать это, я не знаю, правильно ли это, но я хочу, чтобы этот массив действовал как локальная переменная в дочернем процессе, и я хочу обновлять его каждый раз, когда получаю те же или новые символы?

Спасибо

Комментарии:

1. если вы хотите знать, когда отправлять данные обратно из дочернего процесса, вы можете отправить их обратно в момент получения EOF от родительского процесса. это означает, что read() возвращает -1. Проверьте это и верните данные через канал.

2. Но как мне сохранить данные и обновить их, пока я в своем цикле чтения

3. fork создает два процесса, и поэтому они будут выполняться одновременно. вы отправляете данные из дочернего процесса только после завершения его обработки (это означает, что цикл while завершен), и вы можете получить данные в родительском процессе через некоторое время.

4. Итак, чтобы было понятно, потому что я изучаю c, сначала я разветвляюсь, чтобы создать дочерний элемент, родитель прочитает стандартный идентификатор, он прочитает первый символ, который является A, и отправит его дочернему элементу. дочерний элемент сохранит A в своем массиве, затем вернется к родительскому элементу, затем родитель будетотправьте следующий, и мы делаем это до конца, но означает ли это, что дочерний процесс тоже должен быть зациклен?

5. точно, дочерний элемент должен выполнять цикл до тех пор, пока EOF или пока не скажет n , что будет проще. таким образом, в тот момент, когда вы нажимаете enter, цикл завершается, и дочерний процесс получает все это .. родительский процесс будет отправлять данные только при нажатии клавиши ENTER, поэтому, если вы не нажали enter, дочерний процесс будет продолжать ждать данных. вы можете использовать a select() в цикле, чтобы увидеть, есть ли какие-либо данные для чтения из канала. man7.org/linux/man-pages/man2/select . 2.html

Ответ №1:

 if( pid_child == 0){

 // child code

    close(pipe_1[1]);
    close(pipe_2[0]);
    fd_set inputfd;
    FD_ZERO(inputfd);  // zero out fd set
    FD_SET(pipe_1[0], amp;inputfd);  // add input pipe to set
    int state = select(pipe_1[0]   1, amp;inputfd, NULL, NULL, NULL); // wait until input arrives
    if( FD_ISSET(pipe_1[0], amp;inputfd) )
    { read(pipe_1[0], amp;caract, sizeof(char)); }
    // process it and send it back
}else {
   // parent area
    // you could also do a select before sending the data - for stdin - see link 
    while((c = fgetc(file)) != EOF){
        if((c >= 'A' amp;amp; c <= 'Z') || (c >= 'a' amp;amp; c <= 'z')){

             close(pipe_1[0]);
             close(pipe_2[1]);

             write(pipe_1[1], amp;c, sizeof(char));
        } 
    }
    // do a select here as well and wait for input to come from the user
    fd_set child_input;
    FD_ZERO(child_input);
    FD_SET(pipe_1[1], amp;child_input);   // i'm assuming pipe_1[1] is input pipe
    select(pipe_1[1]   1, amp;child_input, NULL, NULL, NULL);
    if( FD_ISSET(pipe_1[1], amp;child_input) )
          // child has sent back data, process it
 }
  

— выберите пример: https://beej.us/guide/bgnet/html/multi/advanced.html#select