C / UNIX进程间通信使用管道发送字符串

时间:2016-02-21 09:24:37

标签: c unix time pipe ipc

我正在写一个代码,其中孩子和父母应该给彼此提供时间信息,接收者应该打印它。当我在父进程上找到时间并尝试在父进程上打印它工作正常。但是当我尝试要通过管道发送它,它会写一个带有奇怪问号和az字母的行。如果有人试图执行代码,我会注释最后一行。对凌乱的代码感到厌烦,但我无法在当前的键盘中修复它。

{5,10}

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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);
  }