Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading “只读一个”;讯息;每次都是从管子里出来的?_Multithreading_Unix_Io_Pipe - Fatal编程技术网

Multithreading “只读一个”;讯息;每次都是从管子里出来的?

Multithreading “只读一个”;讯息;每次都是从管子里出来的?,multithreading,unix,io,pipe,Multithreading,Unix,Io,Pipe,我有两个进程与管道相连 一个进程有多个线程在管道上写入消息 另一个进程读取管道并处理消息 问题是,当进程读取管道时,它会一个接一个地获取所有消息。有没有办法一次只看一条消息 首先,我使用写和读函数,直接使用文件描述符。 然后我尝试将它们作为文件处理,使用fdopen、fread和fwrite,但它仍然同时读取所有数据 消息的大小每次都会改变,因此我无法通过读取固定数量的字符来修复它。很久以前,在POSIX成为世界上已知概念之前,至少有一个版本的Unix维护了这样的内容,即写入小于管道缓冲区中剩余

我有两个进程与管道相连

一个进程有多个线程在管道上写入消息

另一个进程读取管道并处理消息

问题是,当进程读取管道时,它会一个接一个地获取所有消息。有没有办法一次只看一条消息

首先,我使用写和读函数,直接使用文件描述符。 然后我尝试将它们作为文件处理,使用fdopen、fread和fwrite,但它仍然同时读取所有数据


消息的大小每次都会改变,因此我无法通过读取固定数量的字符来修复它。

很久以前,在POSIX成为世界上已知概念之前,至少有一个版本的Unix维护了这样的内容,即写入小于管道缓冲区中剩余空间大小的内容被读取为与写入管道的数据包大小相对应的原子块,受您试图读取足够数据的限制。不幸的是(或者我的意思是“很明显”),我不能再证明情况是这样了——我已经有四分之一个多世纪没有使用过相关的硬件和O/S了

然而,反例证明MacOSX不再像那样处理读取端(尽管POSIX确实保证,如果写入的请求大小足够小,则调用是原子的)。这对我来说是个惊喜

反例-代码 示例输出 在编写代码时添加线程 创建线程来进行编写并不是那么难。代码仍然使用
rand()
,但是
rand()
不能保证线程安全,因此它可能没有您想要的那么好。另一方面,此代码只是使用
rand()
生成可变大小的消息;它的完美表现并不重要

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

static void childish(int fd)
{
    char nbytes;
    int  pid = getpid();
    while (read(fd, &nbytes, sizeof(nbytes)) == sizeof(nbytes))
    {
        char buffer[1024];
        int  actual;
        if ((actual = read(fd, buffer, nbytes)) != nbytes)
        {
            fprintf(stderr, "%.5d: short read (wanted %d, actual %d)\n", pid, nbytes, actual);
            break;
        }
        printf("%.5d: %.4d R <<%.*s>>\n", pid, nbytes, nbytes, buffer);
        fflush(stdout);
    }
    printf("%.5d: exiting\n", pid);
    exit(0);
}

static void *p_thread(void *data)
{
    int fd = *(int *)data;
    char message[] = "\000The Quick Brown Fox Jumped Over The Lazy Dog";
    int  pid = getpid();
    for (int i = 0; i < 20; i++)
    {
        int nbytes;
        do
        {
            nbytes = rand() % (sizeof(message) - 1);
        } while (nbytes == 0);
        message[0] = nbytes;
        if (write(fd, message, nbytes + 1) != (nbytes + 1))
            break;
        printf("%.5d: %.4d W <<%.*s>>\n", pid, nbytes, nbytes, message+1);
        fflush(stdout);
    }
    printf("%.5d: thread exiting\n", pid);
    return(0);
}

static void parental(int fd)
{
    enum { NUM_THREADS = 3 };
    pthread_t thr[NUM_THREADS];
    int  pid = getpid();
    for (int i = 0; i < NUM_THREADS; i++)
    {
        if (pthread_create(&thr[i], 0, p_thread, (void *)&fd) != 0)
        {
            fprintf(stderr, "%.5d: failed to create thread number %d\n", pid, i);
            exit(EXIT_FAILURE);
        }
    }
    for (int i = 0; i < NUM_THREADS; i++)
    {
        if (pthread_join(thr[i], 0) != 0)
        {
            fprintf(stderr, "%.5d: failed to join thread number %d\n", pid, i);
            exit(EXIT_FAILURE);
        }
    }
    printf("%.5d: master thread exiting\n", pid);
    exit(EXIT_SUCCESS);
}

int main(void)
{
    int fd[2];
    pipe(fd);
    pid_t pid = fork();
    if (pid < 0)
        fprintf(stderr, "failed to fork\n");
    else if (pid == 0)
    {
        close(fd[1]);
        childish(fd[0]);
    }
    else
    {
        close(fd[0]);
        parental(fd[1]);
    }
    return EXIT_FAILURE;  // Failed to fork
}
#包括
#包括
#包括
#包括
#包括
静态无效幼稚(int-fd)
{
半字节;
int pid=getpid();
而(读取(fd,&nbytes,sizeof(nbytes))==sizeof(nbytes))
{
字符缓冲区[1024];
int实际值;
如果((实际=读取(fd,缓冲区,N字节))!=N字节)
{
fprintf(标准,“%.5d:短读(需要%d,实际%d)\n”,pid,n字节,实际值);
打破
}
printf(“%.5d:%.4d R\n”,pid,n字节,n字节,缓冲区);
fflush(stdout);
}
printf(“%.5d:正在退出\n”,pid);
出口(0);
}
静态void*p_线程(void*data)
{
int fd=*(int*)数据;
char message[]=“\000敏捷的棕色狐狸跳过了懒狗”;
int pid=getpid();
对于(int i=0;i<20;i++)
{
整数字节;
做
{
nbytes=rand()%(sizeof(message)-1);
}而(n字节==0);
消息[0]=N字节;
如果(写入(fd,消息,N字节+1)!=(N字节+1))
打破
printf(“%.5d:%.4d W\n”,pid,n字节,n字节,消息+1);
fflush(stdout);
}
printf(“%.5d:线程退出\n”,pid);
返回(0);
}
静态无效(int fd)
{
枚举{NUM_THREADS=3};
pthread_t thr[NUM_THREADS];
int pid=getpid();
对于(inti=0;i

请注意,线程函数
p_thread()
几乎是以前的
parent
函数的副本,但是新的
parent()
函数协调三个线程的创建和终止。
childish()
main()
中的代码根本不需要更改(尽管我在
childish()
中的打印中添加了
R
,以匹配
p\u-thread()
中代码中的
W

很久以前,在POSIX成为世界任何地方的已知概念之前,至少有一个版本的Unix维护了这样的内容,即写入小于管道缓冲区中剩余空间大小的内容被读取为与写入管道的数据包大小相对应的原子块,受您试图读取足够数据的限制。不幸的是(或者我的意思是“很明显”),我不能再证明情况是这样了——我已经有四分之一个多世纪没有使用过相关的硬件和O/S了

然而,反例证明MacOSX不再像那样处理读取端(尽管POSIX确实保证,如果写入的请求大小足够小,则调用是原子的)。这对我来说是个惊喜

反例-代码 示例输出 在编写代码时添加线程 创建线程来进行编写并不是那么难。代码仍然使用
rand()
,但是
rand()
不能保证线程安全,因此它可能没有您想要的那么好。另一方面,此代码只是使用
rand()
生成可变大小的消息;它的完美表现并不重要

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

static void childish(int fd)
{
    char nbytes;
    int  pid = getpid();
    while (read(fd, &nbytes, sizeof(nbytes)) == sizeof(nbytes))
    {
        char buffer[1024];
        int  actual;
        if ((actual = read(fd, buffer, nbytes)) != nbytes)
        {
            fprintf(stderr, "%.5d: short read (wanted %d, actual %d)\n", pid, nbytes, actual);
            break;
        }
        printf("%.5d: %.4d R <<%.*s>>\n", pid, nbytes, nbytes, buffer);
        fflush(stdout);
    }
    printf("%.5d: exiting\n", pid);
    exit(0);
}

static void *p_thread(void *data)
{
    int fd = *(int *)data;
    char message[] = "\000The Quick Brown Fox Jumped Over The Lazy Dog";
    int  pid = getpid();
    for (int i = 0; i < 20; i++)
    {
        int nbytes;
        do
        {
            nbytes = rand() % (sizeof(message) - 1);
        } while (nbytes == 0);
        message[0] = nbytes;
        if (write(fd, message, nbytes + 1) != (nbytes + 1))
            break;
        printf("%.5d: %.4d W <<%.*s>>\n", pid, nbytes, nbytes, message+1);
        fflush(stdout);
    }
    printf("%.5d: thread exiting\n", pid);
    return(0);
}

static void parental(int fd)
{
    enum { NUM_THREADS = 3 };
    pthread_t thr[NUM_THREADS];
    int  pid = getpid();
    for (int i = 0; i < NUM_THREADS; i++)
    {
        if (pthread_create(&thr[i], 0, p_thread, (void *)&fd) != 0)
        {
            fprintf(stderr, "%.5d: failed to create thread number %d\n", pid, i);
            exit(EXIT_FAILURE);
        }
    }
    for (int i = 0; i < NUM_THREADS; i++)
    {
        if (pthread_join(thr[i], 0) != 0)
        {
            fprintf(stderr, "%.5d: failed to join thread number %d\n", pid, i);
            exit(EXIT_FAILURE);
        }
    }
    printf("%.5d: master thread exiting\n", pid);
    exit(EXIT_SUCCESS);
}

int main(void)
{
    int fd[2];
    pipe(fd);
    pid_t pid = fork();
    if (pid < 0)
        fprintf(stderr, "failed to fork\n");
    else if (pid == 0)
    {
        close(fd[1]);
        childish(fd[0]);
    }
    else
    {
        close(fd[0]);
        parental(fd[1]);
    }
    return EXIT_FAILURE;  // Failed to fork
}
#包括
#包括
#包括
#包括
#包括
静态无效幼稚(int-fd)
{
半字节;
int pid=getpid();
当(
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>
#include <unistd.h>

static void childish(int fd)
{
    int  nbytes;
    int  pid = getpid();
    while (read(fd, &nbytes, sizeof(nbytes)) == sizeof(nbytes))
    {
        char buffer[1024];
        int  actual;
        if ((actual = read(fd, buffer, nbytes)) != nbytes)
        {
            fprintf(stderr, "%.5d: short read (wanted %d, actual %d)\n", pid, nbytes, actual);
            break;
        }
        printf("%.5d: %.4d <<%.*s>>\n", pid, nbytes, nbytes, buffer);
        fflush(stdout);
    }
    printf("%.5d: exiting\n", pid);
    exit(0);
}

static void parental(int fd)
{
    char message[] = "The Quick Brown Fox Jumped Over The Lazy Dog";
    int nbytes = 0;
    struct iovec req[2];
    req[0].iov_base = &nbytes;
    req[0].iov_len  = sizeof(nbytes);
    req[1].iov_base = message;
    req[1].iov_len  = 0;
    int  pid = getpid();
    for (int i = 0; i < 20; i++)
    {
        do
        {
            nbytes = rand() % (sizeof(message) - 1);
        } while (nbytes == 0);
        req[1].iov_len = nbytes;
        if (writev(fd, req, 2) != (int)(nbytes + sizeof(nbytes)))
            break;
        printf("%.5d: %.4d <<%.*s>>\n", pid, nbytes, nbytes, message);
        fflush(stdout);
    }
    printf("%.5d: exiting\n", pid);
    exit(0);
}

int main(void)
{
    int fd[2];
    pipe(fd);
    pid_t pid = fork();
    if (pid < 0)
        fprintf(stderr, "failed to fork\n");
    else if (pid == 0)
    {
        close(fd[1]);
        childish(fd[0]);
    }
    else
    {
        close(fd[0]);
        parental(fd[1]);
    }
    return EXIT_FAILURE;  // Failed to fork
}
86798: 0043 <<The Quick Brown Fox Jumped Over The Lazy Do>>
86798: 0001 <<T>>
86798: 0033 <<The Quick Brown Fox Jumped Over T>>
86798: 0006 <<The Qu>>
86798: 0030 <<The Quick Brown Fox Jumped Ove>>
86798: 0036 <<The Quick Brown Fox Jumped Over The >>
86798: 0024 <<The Quick Brown Fox Jump>>
86798: 0022 <<The Quick Brown Fox Ju>>
86798: 0031 <<The Quick Brown Fox Jumped Over>>
86798: 0037 <<The Quick Brown Fox Jumped Over The L>>
86798: 0028 <<The Quick Brown Fox Jumped O>>
86798: 0017 <<The Quick Brown F>>
86798: 0032 <<The Quick Brown Fox Jumped Over >>
86798: 0038 <<The Quick Brown Fox Jumped Over The La>>
86798: 0019 <<The Quick Brown Fox>>
86798: 0007 <<The Qui>>
86798: 0023 <<The Quick Brown Fox Jum>>
86798: 0005 <<The Q>>
86798: 0020 <<The Quick Brown Fox >>
86798: 0004 <<The >>
86798: exiting
86799: 0043 <<The Quick Brown Fox Jumped Over The Lazy Do>>
86799: 0001 <<T>>
86799: 0033 <<The Quick Brown Fox Jumped Over T>>
86799: 0006 <<The Qu>>
86799: 0030 <<The Quick Brown Fox Jumped Ove>>
86799: 0036 <<The Quick Brown Fox Jumped Over The >>
86799: 0024 <<The Quick Brown Fox Jump>>
86799: 0022 <<The Quick Brown Fox Ju>>
86799: 0031 <<The Quick Brown Fox Jumped Over>>
86799: 0037 <<The Quick Brown Fox Jumped Over The L>>
86799: 0028 <<The Quick Brown Fox Jumped O>>
86799: 0017 <<The Quick Brown F>>
86799: 0032 <<The Quick Brown Fox Jumped Over >>
86799: 0038 <<The Quick Brown Fox Jumped Over The La>>
86799: 0019 <<The Quick Brown Fox>>
86799: 0007 <<The Qui>>
86799: 0023 <<The Quick Brown Fox Jum>>
86799: 0005 <<The Q>>
86799: 0020 <<The Quick Brown Fox >>
86799: 0004 <<The >>
86799: exiting
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void childish(int fd)
{
    char nbytes;
    int  pid = getpid();
    while (read(fd, &nbytes, sizeof(nbytes)) == sizeof(nbytes))
    {
        char buffer[1024];
        int  actual;
        if ((actual = read(fd, buffer, nbytes)) != nbytes)
        {
            fprintf(stderr, "%.5d: short read (wanted %d, actual %d)\n", pid, nbytes, actual);
            break;
        }
        printf("%.5d: %.4d <<%.*s>>\n", pid, nbytes, nbytes, buffer);
        fflush(stdout);
    }
    printf("%.5d: exiting\n", pid);
    exit(0);
}

static void parental(int fd)
{
    char message[] = "\000The Quick Brown Fox Jumped Over The Lazy Dog";
    int  pid = getpid();
    for (int i = 0; i < 20; i++)
    {
        int nbytes;
        do
        {
            nbytes = rand() % (sizeof(message) - 1);
        } while (nbytes == 0);
        message[0] = nbytes;
        if (write(fd, message, nbytes + 1) != (nbytes + 1))
            break;
        printf("%.5d: %.4d <<%.*s>>\n", pid, nbytes, nbytes, message+1);
        fflush(stdout);
    }
    printf("%.5d: exiting\n", pid);
    exit(0);
}

int main(void)
{
    int fd[2];
    pipe(fd);
    pid_t pid = fork();
    if (pid < 0)
        fprintf(stderr, "failed to fork\n");
    else if (pid == 0)
    {
        close(fd[1]);
        childish(fd[0]);
    }
    else
    {
        close(fd[0]);
        parental(fd[1]);
    }
    return EXIT_FAILURE;  // Failed to fork
}
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static void childish(int fd)
{
    char nbytes;
    int  pid = getpid();
    while (read(fd, &nbytes, sizeof(nbytes)) == sizeof(nbytes))
    {
        char buffer[1024];
        int  actual;
        if ((actual = read(fd, buffer, nbytes)) != nbytes)
        {
            fprintf(stderr, "%.5d: short read (wanted %d, actual %d)\n", pid, nbytes, actual);
            break;
        }
        printf("%.5d: %.4d R <<%.*s>>\n", pid, nbytes, nbytes, buffer);
        fflush(stdout);
    }
    printf("%.5d: exiting\n", pid);
    exit(0);
}

static void *p_thread(void *data)
{
    int fd = *(int *)data;
    char message[] = "\000The Quick Brown Fox Jumped Over The Lazy Dog";
    int  pid = getpid();
    for (int i = 0; i < 20; i++)
    {
        int nbytes;
        do
        {
            nbytes = rand() % (sizeof(message) - 1);
        } while (nbytes == 0);
        message[0] = nbytes;
        if (write(fd, message, nbytes + 1) != (nbytes + 1))
            break;
        printf("%.5d: %.4d W <<%.*s>>\n", pid, nbytes, nbytes, message+1);
        fflush(stdout);
    }
    printf("%.5d: thread exiting\n", pid);
    return(0);
}

static void parental(int fd)
{
    enum { NUM_THREADS = 3 };
    pthread_t thr[NUM_THREADS];
    int  pid = getpid();
    for (int i = 0; i < NUM_THREADS; i++)
    {
        if (pthread_create(&thr[i], 0, p_thread, (void *)&fd) != 0)
        {
            fprintf(stderr, "%.5d: failed to create thread number %d\n", pid, i);
            exit(EXIT_FAILURE);
        }
    }
    for (int i = 0; i < NUM_THREADS; i++)
    {
        if (pthread_join(thr[i], 0) != 0)
        {
            fprintf(stderr, "%.5d: failed to join thread number %d\n", pid, i);
            exit(EXIT_FAILURE);
        }
    }
    printf("%.5d: master thread exiting\n", pid);
    exit(EXIT_SUCCESS);
}

int main(void)
{
    int fd[2];
    pipe(fd);
    pid_t pid = fork();
    if (pid < 0)
        fprintf(stderr, "failed to fork\n");
    else if (pid == 0)
    {
        close(fd[1]);
        childish(fd[0]);
    }
    else
    {
        close(fd[0]);
        parental(fd[1]);
    }
    return EXIT_FAILURE;  // Failed to fork
}