这里发生父进程和子进程的切换?

问题描述:

代码实际做的是从父进程获取输入,并通过管道将其发送给子进程。子进程将其反转,然后通过另一个管道将其发送回父进程。代码中没有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's Pipe"<<endl; 
     perror("Parent's Pipe"); 
     exit(1); 
    } 

    if(pipe(fifoChild)==-1) 
    { 
     cout<<"Problem in creating Child's Pipe"<<endl; 
     perror("Child's 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

你是什么意思的“他们如何工作”? – 2014-09-01 18:45:04

+1

这是“工作”,因为这是管道所做的 - 你为一端写了一些东西,然后从另一端读取它。你在问管道是如何工作的?或者子进程如何继承文件描述符?或者是其他东西? – 2014-09-01 18:46:23

+0

询问“从孩子abc读取”如何执行?上面给出的输出是通过在父进程和子进程之间来回切换产生的......对吧?哪些陈述导致了这一点? – 2014-09-01 18:49:22

通常,read在一个空的管直到数据可通过写入写入结束的管道。

因此,子进程无法继续执行此线,直到它从父进程接收数据;它会阻止等待它:

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

一旦它读取的字符串,它唤醒,逆转它,并将其写回父。家长也可能会当它达到以下行,等待子进程写颠倒字符串阻止:

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

read阻塞行为类似于waitwaitpid阻塞的行为,但它等待使数据到达文件描述符,而不是等待子进程改变状态。

一般来说,父级和子级进程同时执行,除非系统调用中一个或两个进程被阻止。

当您拨打fork()时,会创建第二个进程,并且这两个进程都位于代码中的此位置。判断您是新的子进程还是原始父进程的唯一方法是查看返回值fork()。在documentation中,您可以看到如果fork()返回0,那么您处于子进程中。所以基本上,if(ChildOrParentId==0)语句的then块只能在子进程中运行,而else块只能在父进程中运行。

如果您将这两个块视为不同的程序,其余解释非常简单。父块要求输入一个字符串,将其发送给孩子,等待孩子发回一些东西,然后打印孩子发送的内容。同时,子块等待来自父项的东西,打印它得到的内容,将其反转并打印出来,然后将反转的字符串发送回父项。