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

C/UNIX Interprocess communication sending a string with pipe

我正在编写一个代码,其中 children 和 parent 应该互相提供时间信息,接收者应该打印 it.When 我在 parent 过程中找到时间并尝试在 parent 进程上打印它 它工作 fine.But 当我尝试通过管道发送它时它写了一行带有奇怪的问号和 z letter.I 评论最后一行以防万一有人试图执行代码。抱歉,代码乱七八糟,但我无法在当前键盘上修复它。

  #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);

您的问题是在创建管道之前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;
}

您在创建管道之前分叉了第一个 child。因此,您创建了两个不同的管道:一个在 parent 中,一个在 child 中。之后,如果从第一个child创建的管道读取,readreturns为0,表示没有读取数据。因此,缓冲区中的数据无效并且printf被禁止。始终检查 API 个调用的 return 代码!

用户 "nsilent22" 已经提供了很好的 clean-up 您的代码。在末尾添加 3 个右括号 } 以关闭所有块后,您至少在创建管道后移动叉子:

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

并且在读取调用中,您应该检查 return 代码:

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