从pthread_create向线程化函数传递多个参数
这是我第一次尝试在C中使用线程。我正在创建一个循环边界缓冲区。我知道如何创建线程,但我看到的所有示例都只有接受一个void参数的线程函数,但不幸的是,我的工人规范要求我使用三个,如下所示:从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
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(¶m->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(¶m->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 Leavingmain
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(¶m->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(¶m->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);
}