关于pthread_create()第四个参数的问题

Dstnoe 2010-12-03 10:14:27
 linux下用C开发多线程程序,Linux系统下的多线程遵循POSIX线程接口,称为pthread。
  这是百度百科上的定义:http://baike.baidu.com/view/1797052.htm
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void), void *restrict arg);

Returns: 0 if OK, error number on failure
 由 restrict 修饰的指针是最初唯一对指针所指向的对象进行存取的方法,仅当第二个指针基于第一个时,才能对对象进行存取。对对象的存取都限定于基于由 restrict 修饰的指针表达式中。 由 restrict 修饰的指针主要用于函数形参,或指向由 malloc() 分配的内存空间。restrict 数据类型不改变程序的语义。 编译器能通过作出 restrict 修饰的指针是存取对象的唯一方法的假设,更好地优化某些类型的例程。
  第一个参数为指向线程标识符的指针。
  第二个参数用来设置线程属性。
  第三个参数是线程运行函数的起始地址。
  最后一个参数是运行函数的参数。

当传递参数时,可以直接通过void *(*start_rtn)(void) 传递,如:

#include<stdio.h>
#include<pthread.h>
void* foo(int *a,int *b)
{


printf("pthread :%d\n",++*a);
printf("pthread :%d\n",++*b);

}

int main()
{

int a=0;
int b=0;
pthread_t tid;
int err;
err=pthread_create(&tid,NULL,foo(&a,&b),NULL);
foo(&a,&b);
return 0;
}


unix中的说:
如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。
上面的函数foo(int *a,int *b); 可以传递2个参数啊!!
问一下,第四个参数void *restrict arg 有啥用? 是运行函数的参数啥意思?
...全文
2435 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
lelexin 2011-10-25
  • 打赏
  • 举报
回复
pthread_create第四个参数就是程序传给线程的参数
比如:int i;
pthread_t pid;
pid = pthread_create(&pid, NULL, ThreadProc, (void*)&i);
宇宙漫步者 2011-10-25
  • 打赏
  • 举报
回复
等待合理解释!或许这就像是线程的锁机制一样,要去遵守才是可能得到想要的结果,否则也可以执行,但是结果不可控!但还是期待合理解释,帮顶
长弓成 2011-10-15
  • 打赏
  • 举报
回复
查资料,路过。。。
YTerrenceLau 2010-12-21
  • 打赏
  • 举报
回复
毫无疑问6楼的程序没有问题,关于参数在栈里面,在这里面也没有问题,因为6楼调用了pthread_join函数,主线成会一直等到子线程执行完毕,在子线程执行完毕前,主线程栈不会被释放。

关于楼主的程序的主要执行流程为:
err=pthread_create(&tid,NULL,foo(&a,&b),NULL);
1,先执行一次foo(&a,&b)并获得返回值,在这里很显然返回值是个随机数(大抵就是eax了)
2,这个返回值作为新线程的入口地址(线程入口地址是个随机数哦),参数是NULL,执行新线程
3,段失败错误
Dstnoe 2010-12-21
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 yterrencelau 的回复:]

关于楼主的程序的主要执行流程为:
err=pthread_create(&tid,NULL,foo(&a,&b),NULL);
1,先执行一次foo(&a,&b)并获得返回值,在这里很显然返回值是个随机数(大抵就是eax了)
2,这个返回值作为新线程的入口地址(线程入口地址是个随机数哦),参数是NULL,执行新线程
3,段失败错误

[/Quote]

照18楼所说的,我有几个疑问:
1,这样说,也可以这样传递参数啊,
2, 线程的执行不是 第三个参数所传递的函数的执行吗?
3, 传入的函数执行完后,再执行新线程(本线程,还是下一个线程?)
4,如果传入的函数的执行就是本线程的执行,那么,段错误是哪来的? 是访问随机的 线程入口地址吗?
oyster2008 2010-12-21
  • 打赏
  • 举报
回复
道理很简单,下面这句话其实是先调用了foo这个函数,然后把该函数的返回值传递进去了
之所以编译不报错,那是因为void*在C里面可以隐式转换成其它类型的指针
err=pthread_create(&tid,NULL,foo(&a,&b),NULL);
bianzhonglin 2010-12-21
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 ganjianh8 的回复:]
调用
pthread_create(&tid,NULL,foo(&a,&b),NULL);
的时候
其实是先做
void* Fun = foo(&a,&b);
然后再
pthread_create(&tid,NULL,Fun,NULL);
[/Quote]
蒽,我也这位差不多理解的,这里的&a,&b是不能传参的,只是作函数的声明,真正要传的参数在后面,如果是一个参数,就把那个变量的地址做最后一个参数,函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg的参数传入。
这样说应该好理解吧!
ganjianh8 2010-12-20
  • 打赏
  • 举报
回复
调用
pthread_create(&tid,NULL,foo(&a,&b),NULL);
的时候
其实是先做
void* Fun = foo(&a,&b);
然后再
pthread_create(&tid,NULL,Fun,NULL);
ganjianh8 2010-12-20
  • 打赏
  • 举报
回复
你创建的线程的routine是野指针函数。
laoshizhuce 2010-12-10
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 z05902 的回复:]

第三个参数传入的是线程执行函数的地址
第四个可以根据你的具体需要,传入你需要的参数。
6楼的代码有点问题,函数栈里面的地址不能当成参数传给线程创建函数,不然线程执行的时候访问函数栈的空间估计会出错。
[/Quote]

但是参数传递后这个栈并没有消失啊,我觉得没问题,请指教
laoshizhuce 2010-12-10
  • 打赏
  • 举报
回复
当传递参数时,可以直接通过void *(*start_rtn)(void) 传递 长见识了
xiaocai0001 2010-12-04
  • 打赏
  • 举报
回复
单核的吧, 双核试试...
z05902 2010-12-04
  • 打赏
  • 举报
回复
第三个参数传入的是线程执行函数的地址
第四个可以根据你的具体需要,传入你需要的参数。
6楼的代码有点问题,函数栈里面的地址不能当成参数传给线程创建函数,不然线程执行的时候访问函数栈的空间估计会出错。
阿磊2013 2010-12-04
  • 打赏
  • 举报
回复
参考一下六楼的答案吧。
还有,第三个参数,一般没楼主这么用的吧,一般就是传线程开始执行的那个函数而已。建议楼主多看一下一些别人的代码,然后借鉴一下看别人是怎么用的
Dstnoe 2010-12-04
  • 打赏
  • 举报
回复
双核的啊 AMD 5400+ 啊,继续等待。。。
Dstnoe 2010-12-03
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 xiaocai0001 的回复:]

foo(&a,&b)
括号里的&a, &b不起作用的, 这儿只需要一个函数的入口地址, 参数传不进去的

编译过不能说明问题.
[/Quote]
但是行能运行啊!
输出:
pthread:1
pthread:1
pthread:2
pthread:2
bluejays 2010-12-03
  • 打赏
  • 举报
回复
arg也可以这样用:
#include<stdio.h>
#include<pthread.h>
void* foo(void *args)
{

int *a, *b;
a = ((void**)args)[0];
b = ((void**)args)[1];
printf("pthread :%d\n",++*a);
printf("pthread :%d\n",++*b);

}

int main()
{

int a=0;
int b=0;
void *arg[2] = {&a, &b};
pthread_t tid;
int err;
err=pthread_create(&tid,NULL,foo,arg);
pthread_join(tid, NULL);
printf("main: a=%d, b=%d\n", a, b);
return 0;
}
xiaocai0001 2010-12-03
  • 打赏
  • 举报
回复
foo(&a,&b)
括号里的&a, &b不起作用的, 这儿只需要一个函数的入口地址, 参数传不进去的

编译过不能说明问题.
bluejays 2010-12-03
  • 打赏
  • 举报
回复
象LZ那样应该也可以,把参数从第三个参数传进去,就用不着第四个了
Dstnoe 2010-12-03
  • 打赏
  • 举报
回复
可是,上面的程序能编译通过,没有任何waring啊!
加载更多回复(2)

23,110

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧