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

标签 c linux multithreading

我有三个线程 - 第一个读取句子直到“;”给出,第二个计算这些句子中的字符,第三个显示结果。

好吧,我只做了一句话,但通过管道发送数组似乎会产生一些问题(以及从一个线程读取多个字符串)。

为了阅读,我只能把字符串放一次,不能再放了。甚至整个功能上的互斥锁也不起作用。为什么会这样?

此外,在写入字符串后,我收到“写入:成功”消息。

这里有什么问题吗?

这是代码:

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

编辑。

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

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

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

最佳答案

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

具有三个进程的管道示例。父级向子级发送“hello world”,子级在字符串长度前添加字符串长度并将新字符串发送给孙级,孙级将其打印到标准输出。

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

关于c - 如何使用管道在线程之间发送数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24342988/

相关文章:

multithreading - 计算机如何仅使用几个寄存器?

c - 调用 pthread_exit() 时发生内存泄漏

c - 我如何使用 clone() 系统调用而不是通常的 fork() + exec() 组合?

c - 生成多组组合

c - 取消引用空指针

linux - awk脚本中的命令行输入?

linux - 为什么会出现不兼容的指针类型警告?

c - C 中的系统命令,如何在 ""之间的字符串内传递指针

linux - 读取带有 unicode 字符的文本文件 - Python3

c++ - 创建多线程 C++