C语言 从 pthread_create 向线程函数传递多个参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16230542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 06:10:48  来源:igfitidea点击:

Passing multiple arguments to threaded function from pthread_create

cpthreadsposix

提问by ChrisDevWard

this is my first attempt at threading in C. I am creating a circularly bounded buffer. I know how to create the thread, but all examples I have seen only have threaded functions that accept one void parameter, but unfortunately my worker's specification requires me to use three, as shown here:

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

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

Here is my pthread_create statement

这是我的 pthread_create 语句

pthread_create(&buffer.readThread, NULL, (void *)bufferRead, &readParams)

And my readParams struct/assignments

还有我的 readParams 结构/分配

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

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

Any advice on how to assign each of the struct's parameters after passing to the bufferRead function would be greatly appreciated.

任何关于如何在传递给 bufferRead 函数后分配结构的每个参数的建议将不胜感激。

回答by Daniel Santos

That's because you only really needone parameter. When we have more than one value, as is typically the case, we encapsulate that into a struct. The function type that pthread_create will call is non-negotiable. This is an area where type-casting your function pointer can get you into serious trouble.

那是因为你真的只需要一个参数。当我们有多个值时,通常情况下,我们将其封装到一个结构中。pthread_create 将调用的函数类型是不可协商的。这是一个类型转换你的函数指针可能会给你带来严重麻烦的地方。

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

回答by Valeri Atamaniouk

Start function has to take argument. So your direction is right:

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

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

Then, you need to allocate the variable on heap, not on stack:

然后,您需要在堆上分配变量,而不是在堆栈上:

struct readThreadParams *readParams;

readParams = malloc(sizeof(*readParams));
readParams->b = buffer2;                                                     
readParams->data = out_array;                                                
readParams->count = in_size;

After which you can give it createThread:

之后你可以给它createThread

pthread_create(&buffer.readThread, NULL, bufferRead, readParams);

Thread function shall take only 1 argument (void*):

线程函数应仅采用 1 个参数 (void*):

void *bufferRead(void *arg)
{
    struct readThreadParams *params = arg;
    BoundedBuffer *buffer = params->b;
    char* data = params->data;
    int count = params->count;

    pthread_mutex_lock(&buffer->mutexBuffer);
    <snip>
    pthread_mutex_unlock(&buffer->mutexBuffer);

    return NULL;
}

回答by Jeyaram

You got in the right way.

你走对了路。

The function prototype should be like

函数原型应该是这样的

void*  bufferRead(void *arg)
{
   ....
}

And typecast the argument to required type in thread function. Here, it should be

并将参数类型转换为线程函数中所需的类型。这里应该是

void*  bufferRead(void *arg)
{
     struct readThreadParams *input = (struct readThreadParams*)arg;
}

Passing more than one arguments to pthread function is not possible directly. so mostly formed as structure and passed to the function.

不能直接将多个参数传递给 pthread 函数。所以主要形成结构并传递给函数。

Refer thistutorial for more details on pthreads.

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

回答by autistic

This example borders on preprocessor abuse, but I like it because it demonstrates mimicking default argument values.

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

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