Где здесь происходит переключение родительского процесса и дочернего процесса?

0

То, что на самом деле делает код, принимает входные данные от родительского процесса, отправляет его дочернему процессу через канал. Детский процесс меняет его, а затем отправляет обратно родительскому каналу через другой канал. В коде нет функции waitpid() или wait().

Вопрос в том, как здесь работает процесс переключения? Как работают функции write() и read()?

Вот код:

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

#define li long int

using namespace std;

void ReverseAString(char input[])
{
    li length = strlen(input),i;
    char hold;

    for(i=0;i<length/2;i++)
    {
        hold = input[i];
        input[i] = input[length-(i+1)];
        input[length-(i+1)] = hold;
    }
}

int main()
{
    pid_t ChildOrParentId;
    int fifoParent[2],fifoChild[2],in;


    if(pipe(fifoParent)==-1)
    {
        cout<<"Problem in creating Parent Pipe"<<endl;
        perror("Parent Pipe");
        exit(1);
    }

    if(pipe(fifoChild)==-1)
    {
        cout<<"Problem in creating Child Pipe"<<endl;
        perror("Child Pipe");
        exit(1);
    }

    ChildOrParentId = fork();
    if(ChildOrParentId==0)
    {
        char buf[100],collected[100];

        close(fifoParent[0]);
        close(fifoChild[1]);
        in = 0;
        while(read(fifoChild[0],buf,1)>0)
        {
            collected[in]=buf[0];
            in++;
        }

        collected[in]=0;
        cout<<"Read from Child "<<collected<<endl;
        ReverseAString(collected);
        cout<<"After Reversing: "<<collected<<endl;

        write(fifoParent[1],collected,sizeof(collected));
        close(fifoParent[1]);
    }
    else
    {
        char buf[100],collected[100];

        close(fifoParent[1]);
        close(fifoChild[0]);
        in = 0;
        cout<<"Enter a string: ";
        gets(buf);

        write(fifoChild[1],buf,sizeof(buf));
        close(fifoChild[1]);
        while(read(fifoParent[0],buf,1)>0)
        {
            collected[in] = buf[0];
            in++;
        }

        collected[in] = 0;
        cout<<"Read from Parent "<<collected<<endl;

    }


    return 0;
}

Окно вывода выглядит следующим образом:

Enter a string: abc // abc input given
Read from child abc
After reversing: cba
Read from parent cba
  • 0
    Что вы подразумеваете под «как они работают»?
  • 1
    Это «работает», потому что это то, что делают каналы - вы пишете что-то с одного конца, а читаете с другого. Вы спрашиваете, как работают трубы? Или как файловые дескрипторы наследуются дочерним процессом? Или что-то другое?
Показать ещё 2 комментария
Теги:
process
pipe

2 ответа

1
Лучший ответ

Обычно read на пустых трубах до тех пор, пока данные не станут доступными, записав на конец записи трубы.

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

    while(read(fifoChild[0],buf,1)>0)

После того, как он прочитал строку, она просыпается, меняет ее и записывает обратно родительскому. Родитель также может быть заблокирован, когда достигнет следующей строки, ожидая, пока дочерний процесс напишет обратную строку:

    while(read(fifoParent[0],buf,1)>0)

Поведение блокировки read похоже на поведение блокировки wait или waitpid, но оно ожидает, что данные будут поступать в дескриптор файла, а не ждать, пока дочерний процесс изменит статус.

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

0

В тот момент, когда вы вызываете fork(), создается второй процесс, и оба процесса находятся в этой точке кода. Единственный способ узнать, являетесь ли вы новым дочерним процессом или исходным родительским процессом, - это посмотреть на возвращаемое значение fork(). В документации вы можете видеть, что если fork() возвращает 0, вы находитесь в дочернем процессе. Итак, в основном, then блок if(ChildOrParentId==0) работает только в дочернем процессе, а блок else работает только в родительском процессе.

Остальное объяснение довольно прямолинейно, если вы посмотрите на эти два блока как разные программы. Родительский блок запрашивает строку, отправляет ее ребенку, ждет, когда ребенок отправит что-то обратно, затем распечатает то, что отправил ребенок. Между тем, дочерний блок ждет чего-то от родителя, распечатывает то, что получает, меняет его и печатает, а затем отправляет обратную строку обратно родительскому.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню