从pthread_create向线程化函数传递多个参数

从pthread_create向线程化函数传递多个参数,c,pthreads,posix,C,Pthreads,Posix,这是我第一次尝试在C中使用线程。我正在创建一个循环边界缓冲区。我知道如何创建线程,但我看到的所有示例都只有接受一个void参数的线程函数,但不幸的是,我的工人规范要求我使用三个,如下所示: void bufferRead(BoundedBuffer* buffer, char* data, int count) { pthread_mutex_lock(&buffer->mutexBuffer); <snip> pthread_mutex_unl

这是我第一次尝试在C中使用线程。我正在创建一个循环边界缓冲区。我知道如何创建线程,但我看到的所有示例都只有接受一个void参数的线程函数,但不幸的是,我的工人规范要求我使用三个,如下所示:

void bufferRead(BoundedBuffer* buffer, char* data, int count) {
    pthread_mutex_lock(&buffer->mutexBuffer);
    <snip>
    pthread_mutex_unlock(&buffer->mutexBuffer);
}
以及我的readParams结构/作业

struct readThreadParams {                                                   
    BoundedBuffer b;                                                        
    char* data;                                                             
    int count;                                                              
};                                                                          

struct readThreadParams readParams;                                         
readParams.b = buffer2;                                                     
readParams.data = out_array;                                                
readParams.count = in_size;

对于如何在传递到bufferRead函数后分配每个结构参数的任何建议,我们都将不胜感激。

您得到了正确的方法

函数原型应该是

void*  bufferRead(void *arg)
{
   ....
}
并将参数类型转换为线程函数中所需的类型。在这里,应该是

void*  bufferRead(void *arg)
{
     struct readThreadParams *input = (struct readThreadParams*)arg;
}
无法直接向pthread函数传递多个参数。所以大部分形成为结构并传递给函数


有关pthreads的更多详细信息,请参阅教程。

启动函数必须采用参数。所以你的方向是正确的:

struct readThreadParams {                                                   
    BoundedBuffer *b; 
    char *data;                                                             
    int count;                                                              
};     
然后,您需要在堆上而不是堆栈上分配变量:

struct readThreadParams *readParams;

readParams = malloc(sizeof(*readParams));
readParams->b = buffer2;                                                     
readParams->data = out_array;                                                
readParams->count = in_size;
之后,您可以给它
createThread

pthread_create(&buffer.readThread, NULL, bufferRead, readParams);
线程函数只能接受1个参数(void*):

void*bufferRead(void*arg)
{
结构readThreadParams*params=arg;
BoundedBuffer*buffer=params->b;
char*data=params->data;
int count=参数->计数;
pthread_mutex_lock(&buffer->mutexBuffer);
pthread_mutex_unlock(&buffer->mutexBuffer);
返回NULL;
}

这是因为您实际上只需要一个参数。当我们有多个值时(通常情况下),我们将其封装到一个结构中。pthread_创建将调用的函数类型是不可协商的。这是一个类型转换函数指针会给您带来严重麻烦的领域

#include <pthread.h>
#include <stdlib.h>

struct BoundedBuffer {
    pthread_t readThread;
    pthread_mutex_t mutexBuffer;
} buffer2;

struct readThreadParams {
    struct BoundedBuffer b;
    char* data;
    int count;
};

void *bufferRead (void *context) {
    struct readThreadParams *readParams = context;

    pthread_mutex_lock(&readParams->b.mutexBuffer);
    //<snip>
    pthread_mutex_unlock(&readParams->b.mutexBuffer);

    return NULL;
}

int main(void) {
    int ret;
    char *out_array = malloc(42);
    size_t in_size = 42;

    struct readThreadParams readParams;
    readParams.b = buffer2;
    readParams.data = out_array;
    readParams.count = in_size;

    /* I presume that by "buffer", you really meant the .b member of
     * struct readThreadParams.  Further, this must have a member
     * named readThread of type pthread_t, etc.
     */
    ret = pthread_create(&readParams.b.readThread, NULL, bufferRead, &readParams);

    if (!ret) {
        pthread_join(&readParams.b.readThread, NULL);
    }

    free(out_array);

    return ret;
}
#包括
#包括
结构绑定缓冲区{
pthread_t readThread;
pthread_mutex_t mutexBuffer;
}缓冲区2;
结构readThreadParams{
结构绑定缓冲区b;
字符*数据;
整数计数;
};
void*bufferRead(void*context){
struct readThreadParams*readParams=context;
pthread_mutex_lock(&readParams->b.mutexBuffer);
//
pthread_mutex_unlock(&readParams->b.mutexBuffer);
返回NULL;
}
内部主(空){
int ret;
char*out_数组=malloc(42);
尺寸=42;
结构readThreadParams readParams;
readParams.b=buffer2;
readParams.data=out\u数组;
readParams.count=单位为;
/*我想你所说的“缓冲区”是指
*struct readThreadParams。此外,它必须有一个成员
*pthread\u t等类型的命名readThread。
*/
ret=pthread_create(&readParams.b.readThread,NULL,bufferRead,&readParams);
如果(!ret){
pthread_join(&readParams.b.readThread,NULL);
}
空闲(out_数组);
返回ret;
}

这个示例近乎预处理器滥用,但我喜欢它,因为它演示了模仿默认参数值

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

typedef char *BoundedBuffer;

struct read_thread_param {  
    pthread_t thread;                                                 
    BoundedBuffer buffer;                                                        
    char* data;                                                             
    int count;                                                              
}; 

void buffer_read(BoundedBuffer* buffer, char* data, int count) {
    pthread_mutex_lock(&buffer->mutexBuffer);
    /*snip*/
    pthread_mutex_unlock(&buffer->mutexBuffer);
}

void *buffer_read_entrance(void *object) {
    struct read_thread_param *param = object;
    if (param->thread != 0) {
        buffer_read(&param->buffer, param->data, param->count);
        free(param);
        return NULL;
    }

    param = malloc(sizeof *param);

    /* TODO: Handle allocation error */
    assert(param != NULL);

    memcpy(param, object, sizeof *param);

    /* TODO: Handle thread creation error */
    assert(pthread_create(&param->thread, NULL, buffer_read_entrance, param) == 0);
    return NULL;
}

#define buffer_read_entrance(...) buffer_read_entrance(&(struct read_thread_param) { .thread = 0, __VA_ARGS__ })
void buffer_read(BoundedBuffer* buffer, char* data, int count);

int main(void) {
    buffer_read_entrance(.buffer = "hello world", .count = 42);
}
#包括
#包括
#包括
#包括
#包括
typedef char*BoundedBuffer;
结构读取线程参数{
pthread\u t线程;
有界缓冲区;
字符*数据;
整数计数;
}; 
无效缓冲区读取(BoundedBuffer*缓冲区,字符*数据,整数计数){
pthread_mutex_lock(&buffer->mutexBuffer);
/*剪断*/
pthread_mutex_unlock(&buffer->mutexBuffer);
}
无效*缓冲区\读取\入口(无效*对象){
结构读取线程参数*参数=对象;
如果(参数->线程!=0){
缓冲区读取(¶m->buffer,param->data,param->count);
自由(param);
返回NULL;
}
param=malloc(sizeof*param);
/*TODO:句柄分配错误*/
断言(参数!=NULL);
memcpy(参数、对象、大小f*param);
/*TODO:处理线程创建错误*/
断言(pthread_create(¶m->thread,NULL,buffer_read_entry,param)==0);
返回NULL;
}
#定义缓冲区读取入口(…)缓冲区读取入口(&(结构读取线程参数){.thread=0,uuu VA_参数})
void buffer_read(BoundedBuffer*buffer,char*data,int count);
内部主(空){
缓冲区读取入口(.buffer=“hello world”,.count=42);
}

感谢您的快速回复!我只是想知道,还有什么方法可以继续使用我目前拥有的函数原型吗?你可以进行类型转换和创建。但是没有用。所以建议使用
void*()(void*)
。@ChrisDevWard不,您不能。好的,使用该原型的唯一方法是直接从pthread库将调用的void*start_例程(void*)函数调用它,但这将不必要地引入另一个函数调用的开销。@Jeyaram另外,从void*到另一个指针类型的类型转换也不是严格要求的(我不确定这可能需要什么样的C标准),但从另一个指针类型转换为void*确实需要显式类型转换。@Danielsanto从
void*
转换为任何指向对象类型的指针,然后再转换回来,值应转换为相等值。这在所有C标准中都是如此。如果试图访问它所属的对象,则存在未定义行为的某些方面指向,指针没有适当对齐以存储该类型,或者指针没有指向具有适当大小或表示形式的对象。如果它是main中的局部变量,这不是问题。如果退出main,则程序仍将终止,以便在程序运行时变量始终存在。@jcoder Leaving
main
doesn并不意味着程序立即终止。用于线程间通信的自动(非堆、非静态)变量充其量也是一个值得怀疑的想法。好吧,你是对的,离开main和执行exit之间有一个很小的间隔。所以这是不安全的。我同意。我想写一些关于只要你创建线程obje,你的时间是多长的
#include <pthread.h>
#include <stdlib.h>

struct BoundedBuffer {
    pthread_t readThread;
    pthread_mutex_t mutexBuffer;
} buffer2;

struct readThreadParams {
    struct BoundedBuffer b;
    char* data;
    int count;
};

void *bufferRead (void *context) {
    struct readThreadParams *readParams = context;

    pthread_mutex_lock(&readParams->b.mutexBuffer);
    //<snip>
    pthread_mutex_unlock(&readParams->b.mutexBuffer);

    return NULL;
}

int main(void) {
    int ret;
    char *out_array = malloc(42);
    size_t in_size = 42;

    struct readThreadParams readParams;
    readParams.b = buffer2;
    readParams.data = out_array;
    readParams.count = in_size;

    /* I presume that by "buffer", you really meant the .b member of
     * struct readThreadParams.  Further, this must have a member
     * named readThread of type pthread_t, etc.
     */
    ret = pthread_create(&readParams.b.readThread, NULL, bufferRead, &readParams);

    if (!ret) {
        pthread_join(&readParams.b.readThread, NULL);
    }

    free(out_array);

    return ret;
}
#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char *BoundedBuffer;

struct read_thread_param {  
    pthread_t thread;                                                 
    BoundedBuffer buffer;                                                        
    char* data;                                                             
    int count;                                                              
}; 

void buffer_read(BoundedBuffer* buffer, char* data, int count) {
    pthread_mutex_lock(&buffer->mutexBuffer);
    /*snip*/
    pthread_mutex_unlock(&buffer->mutexBuffer);
}

void *buffer_read_entrance(void *object) {
    struct read_thread_param *param = object;
    if (param->thread != 0) {
        buffer_read(&param->buffer, param->data, param->count);
        free(param);
        return NULL;
    }

    param = malloc(sizeof *param);

    /* TODO: Handle allocation error */
    assert(param != NULL);

    memcpy(param, object, sizeof *param);

    /* TODO: Handle thread creation error */
    assert(pthread_create(&param->thread, NULL, buffer_read_entrance, param) == 0);
    return NULL;
}

#define buffer_read_entrance(...) buffer_read_entrance(&(struct read_thread_param) { .thread = 0, __VA_ARGS__ })
void buffer_read(BoundedBuffer* buffer, char* data, int count);

int main(void) {
    buffer_read_entrance(.buffer = "hello world", .count = 42);
}