使用两个单向管道的双向通信

时间:2017-12-12 16:27:51

标签: c unix pipe ipc

您已经编写了一个代码,以便父母通过管道发送消息,孩子接收它并将其打印到屏幕上...然后孩子应该回复一个并且父母在管道内打印msg ...代码与从父到子的通信完美地工作..但是当涉及到相反的close()返回错误并且消息没有传递时...注意我也使用共享内存来进行一些同步和控制..我知道在孩子和父母之间有一种特殊类型的管道..但我想使用一般情况一,如果它是为那个目的工作,请告诉我,如果这是真的..这里是代码

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <errno.h>
#include <sched.h>
#include <string.h>
int main()
{
////creating shared memory with check///
int  shmid ;
int err;
char *shm;
shmid = shmget(IPC_PRIVATE,3 ,IPC_CREAT | IPC_EXCL | 0666 );
shm=shmat(shmid,0, IPC_CREAT | IPC_EXCL | 0666  );
if (shmid > -1)
{
printf("shared memory created succefully\n");
shm[0]='C';
shm[1]='C';
shm[2]='C';
}
else
{
return 0;
}


/////////////////////////////////////////

//////////making pipe with check/////////
int  testpipe[2];
int  size_ptr ;
char buff1[51];
char buff2[51];
char buff3[51];
char buff4[51];
int check;
check = pipe(testpipe);
if (check > -1)
{
printf("pipe created succefully\n");
}
else
{
return 0 ;
}
////////////////////////////////////////


///////////making new process///////////
pid_t pid ;
pid = fork();
////////////////////////////////////////


///////////Executing process ///////////
    if (pid > 0) //am in parent
    {


//////////partA////////////////////
     strcpy(buff1,"Hi am tweeting now ..\n");
    // err = close(testpipe[0]);
     printf("... Close state %d \n",err);
     write(testpipe[1],buff1,25);
     close(testpipe[1]);
     printf("partA Ended ... Close state %d \n");

/////////////////////////////////////
shm[0] = 'O'; // lock 2 is opened here

shm[1] = 'C'; // lock 1 is closed
while(shm[1] != 'O');
/////////////////////////////////////

//////////partD///////////////////
    //close(testpipe[1]);
    err = read(testpipe[0],buff4,25);
    //close(testpipe[1]);
    printf(" error state%i \n",err);
    printf("the output is : %s\n",buff4);
    printf("part D Ended ...\n");
    printf("Close state %d ... %i \n",err,EACCES);
    shmdt(shm);
    return 0;

    }
    else if (pid ==0) // am in child now
    {
    while(shm[0]!= 'O');  //from child read'

    ///////////////////////////////////

    //////////partb////////////////////
    read(testpipe[0],buff2,25);
    //err = close(testpipe[0]);
    printf("Close state %d \n",err);
    printf("the output is : %s\n",buff2);
    printf("partB Ended ... Close state %d\n",err);
    //close(testpipe[0]);
    //////////////////////////////////

    ///////////////    /part c////////////
     close(testpipe[0]);
     err = write(testpipe[1],buff3,25);
     printf("III... Close state %d \n",err);
     err = close(testpipe[1]);
     printf("Close state %d \n",err);
     printf("partC Ended ..\n");
     shm[1] ='O';
/////////////////////////////////////////////////
     //shm[1] = 'O';
     shm[0] = 'C';
     while(shm[0]!= 'O');
     printf("process child closed\n");

    }
    else{
     printf("Error Ocuured");
    }
//////////////////////////////////////////



}

编辑:我改变了标题 a screen shot of the terminal output here :

2 个答案:

答案 0 :(得分:2)

  

您已编写代码,以便父级通过a发送消息   管子,孩子接收它并将其打印到屏幕......然后是孩子   应该回复一个,父母在管道内打印msg ..   代码与从父母到孩子的沟通完美配合。   但是当涉及到相反的close()返回错误和   消息未通过...

您的代码会打印有关close()的消息,但正如您的代码所示,这些消息大部分都不会报告close()次呼叫的实际返回值。你有各种各样的错误。

但是你怎么知道这条消息没有通过?您从buff3写入管道,该管道从未初始化或写入。那么,您如何识别该消息是否已通过?如果您幸运,则传递第一个字节为'\0'的消息,这样当您打印时,它将用作空字符串。

  

请注意,我还使用了共享内存   一些同步和控制..

不,你没有。一个可以使用共享内存来托管同步对象,例如进程共享信号量和互斥量,但共享内存本身不提供任何同步语义。因此,您的程序包含数据争用,因此其行为未定义。

我会推荐信号量用于你似乎正在执行的那种锁定,除了它首先似乎没有必要。适当的管道使用不需要额外的同步。

在这种情况下,“适当的”是为每个通信方向使用不同的管道。虽然可以在两个方向上只使用一个,但这样做是混乱和不必要的。

  

我知道有一种特殊的类型   儿童与父母之间的管道

父进程和子进程之间没有特殊类型的管道。

进程通常通过调用pipe()本身或通过从父进程继承一个或多个打开的管道末端文件描述符来获取对通过pipe()函数创建的管道的访问。以这种方式获取访问权限时,只有具有共同祖先的进程才能通过管道相互通信。虽然父进程和子进程之间的通信是一个常见的例子,但这种管道绝不会受限于特定的使用模式。

总体:

  • 我的主要建议是抛弃共享内存和非工作“锁”,而是使用两个管道,每个方向一个。

  • 如果必须只使用一个管道,请执行正确的同步。出于显而易见的目的,看起来使用一个或两个信号量(进程共享和驻留在共享内存中)足以控制在任何给定时间允许从管道读取哪个进程就足够了。还有其他替代方案,但仅共享内存并不能满足您的需求。

答案 1 :(得分:0)

并使用共享内存同步进程操作(r / w)..它工作..

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <errno.h>
#include <sched.h>
#include <string.h>

#define parent_read parent_child[0]
#define parent_write parent_child[1]
#define child_read child_parent[0]
#define child_write child_parent[1]

int main()
{
////creating shared memory with check///
int  shmid ;
int err;
char *shm;
shmid = shmget(IPC_PRIVATE,4 ,IPC_CREAT | IPC_EXCL | 0666 );
shm=shmat(shmid,0, IPC_CREAT | IPC_EXCL | 0666  );
if (shmid > -1)
{
printf("shared memory created succefully\n");
shm[0]='I';
shm[1]='I';

}
else
{
return 0;
}


/////////////////////////////////////////

//////////making pipe with check/////////
int  parent_child[2];
int  child_parent[2];
int  size_ptr ;
char buff1[51];
char buff2[51];
char buff3[51];
char buff4[51];
int check1;
int check2;
check1 = pipe(parent_child);
check2 = pipe(child_parent);
if (check1 > -1 && check2 > -1)
{
printf("pipe 1 created succefully\n");
}
else
{
return 0 ;
}
////////////////////////////////////////


///////////making new process///////////
pid_t pid ;
pid = fork();
////////////////////////////////////////


///////////Executing process ///////////






    if (pid > 0) //am in parent
    {


//////////partA////////////////////
     strcpy(buff1,"Hi am tweeting now ..\n");
     close(parent_read);
     printf("... Close state %d \n",err);
     write(parent_write,buff1,25);
     close(parent_write);
     printf("partA Ended ... Close state %d \n");


/////////////////////////////////////
    shm[1] = 'B';
    shm[0]='A';
    while(shm[0] == 'A');
//////////partD///////////////////



    close(child_write);
    printf(" error state%i \n",err);
    read(child_read,buff4,25);
    close(child_read);
    printf("from child  : %s\n",buff4);
    printf("part D Ended ...\n");
    shmdt(shm);
    return 0;

    }








    else if (pid ==0) // am in child now
    {

    while(shm[1] == 'I');
    //////////partb////////////////////
    close(parent_write);
    read(parent_read,buff2,25);
    close(parent_read);
    printf("Close state %d \n",err);
    printf("from parent : %s\n",buff2);
    printf("partB Ended ... Close state %d\n",err);
    //close(testpipe[0]);
    //////////////////////////////////

    ///////////////    /part c////////////
     close(child_read);
     strcpy(buff3,"Hello from the other side...");
     err = write(child_write,buff3,25);
     printf("III... Close state %d \n",err);
     err = close(child_write);
     printf("Close state %d \n",err);
     printf("partC Ended ..\n");
     printf("process child closed\n");
     shm[0]='D';
    }
    else{
     printf("Error Ocuured");
    }
//////////////////////////////////////////



}

父母对孩子:tweety评论 孩子到父母:你好,从另一边

屏幕截图:the output on terminal