【问题标题】:C: connection between threads with pipe, synchronization needed?C:线程与管道之间的连接,需要同步吗?
【发布时间】:2018-06-26 23:32:14
【问题描述】:

我正在处理 C 编程中线程之间的管道通信。 我有 2 个线程:

-thread 1 只是管理一些事件,

-线程2与串口通信;

线程 1 和 2 与管道通信。

如果有一些条件,“事件管理器”线程应该发送一个字符串到“串行管理器”,例如pipe[1],它从串口和 pipe[0] 轮询。 然后,如果有来自 pipe[0] 的字符串,它应该做他的工作。

问题在于线程 1 的写入速度比线程 2 的读取速度快。 所以我的问题是:我如何正确地从管道 [0] 中读取?我如何排队?因为如果我只是以阻塞方式使用 read 只需输入线程 2:

read(pipe[0], string, sizeof(string)-1)

线程 2 读取所有线程 1 的过载消息;

我找到的唯一解决方案是创建另一个阻塞线程1的管道(因为线程1在写入后开始读取,读取是阻塞方式),所以线程1等待线程2完成工作(这很有用因为我可以从线程 2 中得到响应,但我的问题是:这是正确的方法吗?我确信我缺少关于读取功能的一些内容。

【问题讨论】:

  • 是否有充分的理由使用管道在两个线程之间进行通信?这似乎只会造成问题而没有任何好处。
  • 您可以使用消息队列而不是管道。它们是为蜜蜂排队而设计的!看看这个问题:stackoverflow.com/questions/3056307/…
  • 如果您使用线程,那么您可以使用其他同步方式,例如 C 互斥锁?管道主要用于进程通信而不是真正的线程。
  • 线程在同一个“进程上下文”上运行,并且不需要需要管道进行通信。在这种情况下,您可以使用线程同步,例如条件变量或互斥锁。您的问题与并行过程更相关。在这种情况下,您可以使用管道、fifo、带信号量的共享内存或其他进程同步技术。
  • 两个线程的初始化目的是将两者都写入串行,但这会产生很多冲突。所以我使用了二进制信号量(互斥体)和共享存储,效果很好,但代码是不是100%强。然后我意识到只有一个线程应该写入/读取串行,但我需要另一个线程来编码所有要做的事情并将其合成为一个字符串。我认为管道是一个很好的解决方案,我可以在 2 种行为之间进行选择: - 阻塞方式:线程 1 被阻塞,直到线程 2 说没问题(原始目的) - 非阻塞:它们非常独立,线程 1 加载缓冲区高达 65Kbytes ;)

标签: c synchronization pthreads pipe polling


【解决方案1】:

谢谢大家的回答。 我找到了解决方案,不知道它在风格上是否正确,但效果很好,以非阻塞方式使用读取功能。所以只需要在 main 中配置管道:

fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK);

然后确保从 thread1 写入字符串加上 '\0' 字符:

write (pipe_fd[1], string, sizeof(string)+1);

最后在thread2中的读取应该是这样的

int n_bytes, offset;
int pres;
char ch[2];
string[256]; 

pres = poll (....);

if (pres > 0){
    ...
    ...
    /* if it's the pipe_fd[0] ...*/

    offset = 0;
    do{
       n_bytes = read(pipe_fd[0], &ch, 1);
       string[offset] = ch[0];
       offset += n;
    }while(n>0 && ch[0]!='\0' && offset < sizeof(string))

    work_with_message(string)....

就是这样,告诉我你的想法;-)

【讨论】:

    【解决方案2】:

    “[我]这是正确的方式[通过 FIFO 读取可变长度异步消息,一次处理一条]?”

    不,您不需要同步单个生产者通过 FIFO 向单个消费者发送可变长度消息,以便一次处理一条消息。

    正如您在自己的答案中记录的那样,您可以在消息中添加记录终止符。你可以实现一个简单的协议来描述每条消息的长度(c.f. netstrings)。

    您可以在这里借鉴很多先前的做法。例如,您不需要一次读取一个以记录结尾的消息,但可以在本地缓冲部分消息——想想stdio 将字节流转换为行的做法。只有一个消费者的限制使一些事情变得容易。

    “[我]这是正确的方式[在线程之间发送可变长度异步消息]?”

    它可以使用,但可能并不理想。

    面向消息的排队通道可能更适合这里:message queuesdatagram socket pair

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-08
      • 2014-08-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 2016-12-17
      相关资源
      最近更新 更多