如何使用管道在线程之间发送数组?

时间:2014-06-21 15:18:31

标签: c linux multithreading

我有三个主题 - 第一个读取句子直到&#34 ;;"给出,第二个计算这些句子中的字符,第三个显示结果。

嗯,我只用了一句就完成了这个,但是通过管道发送数组似乎会产生一些问题(以及从一个线程中读取多个字符串)。

为了阅读,我只能将字符串放一次,而不是更多。即使是整个函数的互斥量也不起作用。为什么会这样?

此外,写完字符串后我得到了#34;写:成功"信息。

这里有什么问题?

这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
#include <pthread.h>
#include <string.h>

int first[2];
int second[2];

void *input(void *ptr)
{
   char str[100], ch = '0';
   int length, i = 0;

   while(1)
   {
      while(ch != ';')
      {
         printf("Enter the %d message: ", i + 1);
         fflush(stdout);
         length = read(STDIN_FILENO, str, sizeof(str));

         if(write(first[1], str, sizeof(str)) != length)
         {
            perror("write");
            exit(2);
         }  

     if(length <= 0)
         {
            if(length == -1)
               perror("read");
            close(first[1]);
            exit(2);
         }

         i++;
      }
   }
}

void *countChars(void *ptr)
{
   char str[100];
   int length, count = 0, i = 0;

   while(1)
   {
      length = read(first[0], str, sizeof(str));

      if(length <= 0)
      {
         if(length == -1)
            perror("read");
         close(first[0]);
         close(second[1]);
         exit(2);
      }
      if(write(STDOUT_FILENO, str, length) != length)
      {
         perror("write");
         exit(2);
      }

      while(str[count] != '\n') count++;

      write(second[1], &count, sizeof(count));

      count = 0;
   }
}

void *output(void *ptr)
{
   int length, count = 0, i = 0;

   while(1)
   {
      length = read(second[0], &count, sizeof(count));
      if(length < sizeof(count))
      {
         close(second[0]);
         exit(2);
      }

      printf("Number of characters: %d\n", count);
   }
}

int main()
{
   pthread_t t1, t2, t3;

   if(pipe(first) == -1)
   {
      printf("First pipe error");
      exit(1);
   }

   if(pipe(second) == -1)
   {
      printf("Second pipe error");
      exit(1);
   }

   pthread_create(&t1, NULL, input, NULL);
   pthread_create(&t2, NULL, countChars, NULL);
   pthread_create(&t3, NULL, output, NULL);

   pthread_join(t1, NULL);
   pthread_join(t2, NULL);
   pthread_join(t3, NULL);

   return 0;
}

EDIT。

我认为问题是 - 如何从逻辑上解决这个问题?我是这样看的:

Thread1 -> (string) -> Thread2 -> (number of chars) -> Thread3 - save elements somewhere
...
Thread1 -> (ending string) -> Thread2 -> (number of chars removed later) -> Thread3 - display all elements

但如果是这样的话 - 如何让线程像这样一个接一个地运行?如何在结束字符串上停止应用程序?在线程3中保存这些整数值的位置?

2 个答案:

答案 0 :(得分:2)

管道用于在进程之间传递数据,而不是线程。线程在同一进程中运行并且可以访问相同的内存,因此在这种情况下使用管道毫无意义。

具有三个进程的管道示例。 Parent向子节点发送“hello world”,子节点预先设置字符串长度并将该新字符串发送给将其打印到stdout的孙子。

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

void parent(int fd_write) {
    char *msg = "hello world";
    ssize_t len = strlen(msg);
    if (write(fd_write, msg, len) != len) {perror("parent write"); exit(1);}
}

void child(int fd_read, int fd_write) {
    char msg_in[100], msg_out[150];
    ssize_t len = read(fd_read, msg_in, sizeof msg_in);
    if (len == -1) {perror("child read"); exit(1);}
    msg_in[len] = '\0';
    len = sprintf(msg_out, "%d: %s", (int)len, msg_in);
    if (write(fd_write, msg_out, len) != len) {perror("child write"); exit(1);}
}

void grandchild(int fd_read) {
    char msg[256];
    ssize_t len = read(fd_read, msg, sizeof msg);
    if (len == -1) {perror("grandchild read"); exit(1);}
    msg[len] = '\0';
    printf("Msg: %s\n", msg);
}

int main() {
    enum {READ, WRITE};
    pid_t pid;

    int fd[2];
    if (pipe(fd) == -1) {perror("first pipe"); exit(1);}

    pid = fork();
    if (pid == -1) {perror("first fork"); exit(1);}

    if (pid == 0) {
        int fd2[2];
        if (pipe(fd2) == -1) {perror("second pipe"); exit(1);}

        pid = fork();
        if (pid == -1) {perror("second fork"); exit(1);}

        if (pid == 0) {
            close(fd2[WRITE]);
            grandchild(fd2[READ]);
            close(fd2[READ]);
            exit(0);
        }

        close(fd[WRITE]); close(fd2[READ]);
        child(fd[READ], fd2[WRITE]);
        close(fd[READ]); close(fd2[WRITE]);
        wait(NULL);
        exit(0);
    }

    close(fd[READ]);
    parent(fd[WRITE]);
    close(fd[WRITE]);
    wait(NULL);

    return 0;
}

答案 1 :(得分:1)

在输入主题中,在阅读电话length = read(STDIN_FILENO, str, sizeof(str));之后,您正在撰写sizeof(str)而不是length尺寸。

应该是

if(write(first[1], str, length) != length)

另一个问题是您的代码与您的规范不符。 你说输入线程正在读取';',但ch永远不会在循环中被修改。修复你的代码。