【问题标题】:two way communication using two unidirectional pipes使用两个单向管道的双向通信
【发布时间】:2018-05-26 09:54:50
【问题描述】:

您已经编写了一个代码,以便父母通过管道发送消息,孩子接收它并将其打印到屏幕上......然后孩子应该回复一个并且父母在管道内打印味精......代码与父子之间的通信完美配合..但是当涉及到相反的 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 :

【问题讨论】:

  • 管道是单向的。如果父母和孩子都在一个管道上读写,它会变得混乱。使用两个管道。确保你关闭了足够多的文件描述符。
  • 我正在尝试采用两个管道方法......如果这不起作用,我会在这里发布......感谢您的快速评论:)

标签: c unix pipe ipc


【解决方案1】:

您好编写了一个代码,以便父母通过 管道,孩子收到它并将其打印到屏幕上......然后孩子 应该回复一个并且父级在管道内打印味精.. 该代码与父母与孩子的交流完美配合.. 但是当涉及到相反的 close() 返回错误和 消息未通过...

您的代码打印有关close()s 的消息,但就您的代码目前而言,这些消息大部分不会报告您的close() 调用的实际返回值。你有各种各样的错误围绕着它们。

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

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

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

对于您似乎正在执行的锁定类型,我建议使用信号量,但首先它似乎没有必要。适当的管道使用不需要额外的同步。

在这种情况下,“适当”是为每个通信方向使用不同的管道。尽管可以在两个方向上只使用一个,但这样做既麻烦又不必要。

我知道有一种特殊的 孩子和父母之间的管道

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

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


总体:

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

  • 如果您必须只使用一个管道,则执行正确的同步。出于您的明显目的,使用一个或两个信号量(进程共享并驻留在共享内存中)来控制在任何给定时间允许从管道读取的进程似乎就足够了。还有其他选择,但仅共享内存并不能满足您的需要。

【讨论】:

  • 我现在正在尝试这样做..但面临一个问题..这就是父母如何知道孩子创建的描述符...据我所知(如果不正确,请纠正)调用 pipe() 的进程是具有写权限的进程,我将面临分段错误..thnx
  • @AbdAllahTalaat,父母不知道孩子创建的描述符。如果您要使用两个管道,则父级必须同时创建它们。
  • 用语言闪光——这是一个奖励。
  • 哇......是的,伙计们......它也以另一种方式工作......我会用代码和屏幕截图写一个答案谢谢大家......
【解决方案2】:

并使用共享内存同步进程操作 (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");
    }
//////////////////////////////////////////



}

父母对孩子:推特评论 孩子对父母:从另一边打招呼

屏幕截图:the output on terminal

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 2015-06-13
    • 2013-05-02
    • 2015-10-15
    相关资源
    最近更新 更多