使用管道时出现意外输出

时间:2017-04-15 11:05:16

标签: c linux pipe

我是C.的管道新手。 我正在努力写下#34;你好"来自儿童过程的管道&从父进程读取相同的内容,但是我得到了意外的输出。

我使用这段代码:

#include<stdio.h>
#include<unistd.h>
#include<unistd.h>
#include<stdlib.h>

int main()
{
pid_t pid;
int fds[2];
int ret;
char ch[20];

ret = pipe(fds);
if(ret == -1)
{
   perror("pipe failed");
   exit(0);
}

pid = fork();

if (pid == 0)
{
  printf("Child process\n");
  write(fds[1],"Hello",5);

} 

if (pid > 0)
{

   printf("Parent Process\n");
   read(fds[0],ch,15);
   printf("%s\n",ch);

}

return 0;
}

我将此作为输出:

Parent Process
Child process
Helloq.
  

我无法理解为什么这个额外的&#34; q。&#34;来了吗?

3 个答案:

答案 0 :(得分:2)

您正在尝试写入6个字节,但是将大小设置为5.您还需要在Hello结束时发送'\0'

只需将您的写入通话更改为

write(fds[1],"Hello",6);

你应该没事。

答案 1 :(得分:0)

在将数据写入缓冲区之前,在代码中使用<div class="collapse navbar-collapse js-navbar-collapse"> <ul class="nav navbar-nav"> <li><a href="about-us.html">About Us</a></li> <li class="dropdown mega-dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Products<span class="icon ion-ios-arrow-down pull-right"></span></a> <ul class="dropdown-menu mega-dropdown-menu row navigation"> <div class="container"> <li> <div class="col-sm-4"> <div class="left-area"> <button type="button" class="btn all-product-btn">All Products</button> <hr> <ul id="nav"> <li class="active-class" data="Employee"><a href="employee-monitoring-system.html">Employee Monitoring System</a></li> <li data="Hospital"><a href="hospital-management-software/index.html" >Hospital Management Software</a></li> <li data="School"><a href="school-management-system/index.html">School Management System</a></li> <li data="Inventory"><a href="inventory-management-software/index.html">Inventory Management Software</a></li> <li data="Fee"><a href="fee-management-system.html">Fee Management System</a></li> <li data="Lead"><a href="lead-management-system/index.html">Lead Management System</a></li> <li data="Customer"><a href="customer-relationship-management.html">Customer Relationship Management</a></li> <li data="Human"><a href="human-resource-management-software.html">Human Resource Management Software</a></li> <li data="Enterprises"><a href="enterprises-resource-planning.html">Enterprises Resource Planning</a></li> <li data="Commerce"><a href="customize-e-commerce-portals.html">Customize E-Commerce Portals</a></li> </ul> </div> </div> <div id="Employee" class="col-sm-8 nav-hide" > <div class="right-area"> <h3>Employee Monitoring System</h3> <p></p> <div class="col-md-7"> <ul> <li>A Unique System that peforms employee monitoring.</li> <li>Prevents unauthorised exchange of data</li> <li>Could not be identified by a user</li> <li>Captures their Keystrokes</li> <li>Caputres their Screen Shots</li> <li>Uploads text files</li> </ul> </div> <div class="col-md-5"><img src="img/products/ems.jpg" class="img-responsive"></div> </div> </div> </li> <div id="Hospital" class="col-sm-8 nav-hide" style="display:none"> <div class="right-area"> <h3>Hospital Management Software</h3> <div class="col-md-7"> <ul> <li>Reduces the amount of paper work.</li> <li>Recording information about the Patients that come.</li> <li>Generating bills.</li> <li>Recording information related to diagnosis given to Patients.</li> <li>Keeping record of the Immunization provided to children/patients.</li> </ul> </div> <div class="col-md-5"><img src="img/products/hospital.jpg" class="img-responsive"></div> </div> </div> </ul> </div> 函数,该缓冲区使用常量字节填充内存。等,

memset()

完整的代码可能会对您有所帮助。

memset(ch,'\0',20);

答案 2 :(得分:0)

由于您没有记录从管道读取的字节数,因此您的代码正在打印ch变量中已有的垃圾。有很多方法可以解决它。此代码显示其中两个。我使用memset()来确保ch包含一些数据(并且赋值确保它以空值终止)。

#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main(void)
{
    pid_t pid;
    int fds[2];
    int ret;
    char ch[20];

    memset(ch, 'X', sizeof(ch)-1);
    ch[sizeof(ch)-1] = '\0';

    ret = pipe(fds);
    if (ret == -1)
    {
        perror("pipe failed");
        exit(0);
    }

    pid = fork();

    if (pid == 0)
    {
        printf("Child process\n");
        write(fds[1], "Hello", 5);
    }
    else if (pid > 0)
    {
        printf("Parent Process\n");
        int nbytes = read(fds[0], ch, 15);
        printf("[%s]\n", ch);
        printf("[%.*s]\n", nbytes, ch);
        ch[nbytes] = '\0';
        printf("[%s]\n", ch);
    }
    else
        fprintf(stderr, "fork() failed\n");

    return 0;
}

代码记录了写入的字节数(真正勤奋的代码也能确保写入正确数量的数据)。它打印数据3次 - 一次使用您的原始技术,然后使用从管道读取的字节数限制输出,然后空终止数据,以便它可以写为简单的字符串。

%.*s转换规范使用两个值 - 数字和字符串。该数字是将要写入的最大字节数。如果字符串比那短,那就这样吧。如果字符串较长,则忽略多余的字节。

示例输出:

Parent Process
[HelloXXXXXXXXXXXXXX]
[Hello]
[Hello]
Child process

这是管道程序输出的结果。在视觉上,在终端上,我通常得到:

Parent Process
Child process
[HelloXXXXXXXXXXXXXX]
[Hello]
[Hello]

两个输出都有效。注意数据的第一次打印如何包括许多X,因为没有从管道读取空字节。

另一种方法是让孩子将以null结尾的字符串的null写入管道:write(fds[1], "Hello", sizeof("Hello"));。其他选项包括在管道上写入字符串的长度,然后写入数据,然后读取长度和多个字节的数据。这是TLV(类型,长度,值)编码系统的次要变体 - 未明确指定类型,因为它被假定为char