【问题标题】:C/UNIX Interprocess communication sending a string with pipeC/UNIX 进程间通信使用管道发送字符串
【发布时间】:2016-06-02 17:50:02
【问题描述】:

我正在编写一个代码,其中孩子和父母应该互相提供时间信息,接收者应该打印它。当我在父进程上找到时间并尝试在父进程上打印它时它工作正常。但是当我尝试通过管道发送它会写一行带有奇怪的问号和 az 字母的行。我评论了最后一行,以防有人试图执行代码。抱歉代码乱七八糟,但我无法在我当前的键盘上修复它。

  #include<stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include<signal.h>
#include<stdint.h>
#include<string.h>
#include<time.h>


void formatted_time(char* sender_name, char* receiver_name, char output[]);
void formatted_time(  char* sender_name ,  char* receiver_name, char output[])
{
  struct timeval tv;
  time_t nowtime;
  struct tm *nowtm;
char tmbuf[80];
  gettimeofday(&tv, NULL);
  nowtime = tv.tv_sec;
  nowtm = localtime(&nowtime);
  strftime(tmbuf,80 , "%Y-%m-%d %H:%M:%S",
            nowtm);
  sprintf(output, "%s: Time at %s is %s.", receiver_name, sender_name,  tmbuf);
}

int main(int argc, char** argv)
{
     char* parent="Parent";
     char* child1="Child1";
     char* child2="Child2";
    char result[80];
    char buffer[80];
    int firstchild,secondchild,read1,read2,read3;
    firstchild=fork();
        int mypipe[2];
    int mypipe2[2];
    int mypipe3[2];

        if(pipe(mypipe) == -1) {
          perror("Pipe failed");
          exit(1);
        }

        if(firstchild == 0)            //first child
        {
         close(mypipe[1]);    //Closing  the output  of pipe
    sleep(3);
    read1=read(mypipe[0],buffer,sizeof(buffer));    
     printf("%s\n",buffer);



        }else{
    secondchild=fork();        //Creating second child

        if(secondchild == 0)            //2nd child
        {

        sleep(6);


        }else{            //Parent
    close(mypipe[0]);     //Closing the input of pipe
    formatted_time(parent,child1,result);   
    write(mypipe[1],result,strlen(result)+1);
    //printf("%s\n",result);

【问题讨论】:

  • 你在哪里read 来自管道?我在您的代码中的任何地方都看不到它。此外,使用sleep 是尝试同步进程的一种非常粗糙的方法,并且在某些时候肯定会中断。​​
  • 我以为这写到了管道的另一端。写(mypipe[1],结果,strlen(结果)+1); .我可能错了,但这就是我在书中学到的方法
  • 是的,那是write调用,但是read在哪里?
  • 哇,我忘记加了。但它仍然只写了一个问号。
  • 您的代码似乎不完整。

标签: c unix time pipe ipc


【解决方案1】:

在创建管道之前,您正在分叉第一个孩子。因此,您创建了两个不同的管道:一个在父管道中,一个在子管道中。之后,如果从第一个子节点创建的管道中读取,read 返回 0,表示没有读取任何数据。因此,缓冲区中的数据无效,printf 被禁止。始终检查 API 调用的返回码!

用户“nsilent22”已经很好地清理了您的代码。在末尾添加 3 个右括号 } 以关闭所有块后,您至少要在创建管道后移动分叉:

firstchild=fork();
if (firstchild == 0) { // first child

在读取调用时,您应该检查返回码:

  read1=read(mypipe[0],buffer,sizeof(buffer));
  if (read1 <= 0) {
    printf("read failed with code %d\n, ", read1);
  } else {
    printf("%s\n",buffer);
  }

【讨论】:

  • 这似乎也是正确的,感谢您的警告。在阅读您的帖子之前,我成功地将信息从父母传递给第二个孩子,并使用与第一个孩子相同的代码。所以我想出了点什么第一个孩子错了。这有助于我更容易理解
【解决方案2】:

您的问题是您在创建管道之前 打了一个fork 电话。所以实际上你 read 什么也没读,而你的 printf 打印在分配 buffer 的堆栈上的垃圾。

这是您的代码已修复。我还在父级中添加了一个wait 调用,以避免子级打印到控制台:)

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

void formatted_time(char *sender_name,char *receiver_name, char output[]) {
    struct timeval tv;
    time_t nowtime;
    struct tm *nowtm;
    char tmbuf[80];
    gettimeofday(&tv, NULL);
    nowtime = tv.tv_sec;
    nowtm = localtime(&nowtime);
    strftime(tmbuf,80, "%Y-%m-%d %H:%M:%S", nowtm);
    sprintf(output, "%s: Time at %s is %s.", receiver_name, sender_name, tmbuf);
}

int main(int argc, char** argv) {
    char* parent="Parent";
    char* child1="Child1";
    char result[80];
    char buffer[80];
    int firstchild, secondchild, read1;

    int mypipe[2];

    if (pipe(mypipe) == -1) {
        perror("Pipe failed");
        exit(1);
    }

    firstchild=fork();
    if (firstchild == 0) { // first child
        close(mypipe[1]); //Closing  the output  of pipe
        sleep(3);
        read1 = read(mypipe[0], buffer, sizeof(buffer));    
        printf("%d %s\n", read1, buffer);
    } else {
        secondchild=fork(); //Creating second child
        if(secondchild == 0) { //2nd child
            sleep(6);
        } else { //Parent
            close(mypipe[0]); //Closing the input of pipe
            formatted_time(parent, child1, result); 
            int w;
            w = write(mypipe[1], result, strlen(result)+1);
            printf("%d bytes written\n", w);
            wait(NULL);
        }
    }
    return 0;
}

【讨论】:

  • 这行得通。另外在我的代码中,我可以在第二个孩子和父母之间传输数据,这与你所说的相对应。第一个孩子的阅读不起作用,但第二个孩子的阅读正在工作。我还有一个小问题。如何使用另一个管道将信息从孩子一传递给孩子二。从孩子二传递给父母(就像一个循环)。我尝试创建两个不同的管道并让它们等待 3在得到时间之前的几秒钟。但最后所有的时间值都是一样的。
  • @JonathanPark:创建两个额外的管道(一个用于 child1->child2,第二个用于 child2->parent)应该可以工作。您应该在父进程中创建它们。
  • 作为示例,我将更新帖子中的代码并添加另一个管道,但它什么也没打印。
  • 这里从 child1 发送到 child2 的代码:pastebin.com/siW2W2jP(没有错误检查)。
  • 是的,它可以工作。同样,我能够使用第三个管道并将其合并到我的程序的其余部分,这里没有显示。你非常有帮助,谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多