Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1499492
  • 博文数量: 148
  • 博客积分: 2234
  • 博客等级: 大尉
  • 技术积分: 3225
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-17 21:34
个人简介

未来很长。

文章存档

2017年(7)

2016年(4)

2015年(1)

2014年(6)

2013年(31)

2012年(99)

分类: LINUX

2012-08-16 16:12:15

今天看到这个函数,原来它的内部也有不为人知的内涵。
原型:
#include
void pthread_exit(void *rval_ptr);
参数是个空类型的指针,其实关于空类型的意思我在前面已经介绍过了,这里不再赘述。
这个函数的功能就是使一个线程正常退出,终止线程,因为我们知道线程它是依赖进程存在的,如果在线程中使用
exit()函数退出,那么整个的进程将会退出,那么如果此时你还有一些其它需要做的事情没有完成呢,这并不是我们所希望的。
这个参数保存的是线程退出以后返回的值。当然这个参数传递的数值可以不止一个,比如 该我们想传递好几个参数怎么办呢,很快我们就能够想到我们所学过的结构体呀之类的,此时问题就来了,需要注意的问题是:这个结构所使用的内存在调用者完成调用以后必须仍然是有效的,否则就会出现非法访问内存。例如在线程栈上分配了该结构,那么其他的线程在是用这个结构时内存内容可能已经改变了。又如,线程在自己的栈上分配了一个结构然后把指向这个结构的指针传给pthread_exit(),那么当调用pthread_join的线程试图使用该结构时,这个栈有可能已经被撤销,这块内存也已令做他用。
不如我们下面看一个例子来理解:

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<pthread.h>
  3. #include<unistd.h>
  4. #include<stdlib.h>
  5. struct foo{
  6.     int a,b,c,d;
  7. };

  8. void printfoo(const char *s,const struct foo *fp)
  9. {
  10.     printf("s is %s\n",s);
  11.     printf("structure at 0x%x\n",(unsigned)fp);
  12.     printf("foo.a=%d\n",fp->a);
  13.     printf("foo.b=%d\n",fp->b);
  14.     printf("foo.c=%d\n",fp->c);
  15.     printf("foo.d=%d\n",fp->d);
  16. }
  17. void *thr_fn1(void *arg)
  18. {
  19.     struct foo foo={1,2,3,4};
  20.     printfoo("thread 1:\n",&foo);
  21.     pthread_exit((void *)&foo);
  22. }
  23. void * thr_fn2(void *arg)
  24. {
  25.     struct foo foo={4,5,6,7};
  26.     printf("thread 2:ID is %d\n",pthread_self());
  27.     printfoo("thread 2\n",&foo);
  28.     pthread_exit((void *)0);
  29. }
  30. int main(void)
  31. {
  32.     
  33.     int err;
  34.     pthread_t tid1,tid2;
  35.     struct foo *fp;
  36.     err=pthread_create(&tid1,NULL,thr_fn1,NULL);
  37.     if(err!=0){
  38.         printf("create thread 1 is failed\n",strerror(err));
  39.         exit(1);
  40.     }
  41.     err=pthread_join(tid1,(void *)&foo);
  42.     if(err!=0)
  43.             printf("can't join thread1\n");
  44.     sleep(1);
  45.     err=pthread_create(&tid2,NULL,thr_fn2,NULL);
  46.     if(err!=0)
  47.     {
  48.         printf("create thread 2 is failed\n");
  49.          exit(1);
  50.     }
  51.     sleep(1);
  52.     printfoo("parent :\n",&fp);
  53.     exit(0);
  54. }
就比如上面这个例子:我们在线程thr_fn1里面创建了一个结构体变量foo,然后赋值并把它打印出来,最后线程调用pthread_exit退出的时候,我们想把foo这个变量返回给主线程,最后让主线程也打印出这个结构体变量中的值,但是事实上可以吗?我们看一下结果:
s is thread 1:

structure at 0xb7559380
foo.a=1
foo.b=2
foo.c=3
foo.d=4
thread 2:ID is -1219126416
s is thread 2

structure at 0xb7559380
foo.a=4
foo.b=5
foo.c=6
foo.d=7
s is parent :

structure at 0xb7559380
foo.a=-1217691028
foo.b=-1219128428
foo.c=-1217683468
foo.d=-1217691020
结果根本不是我们所想到的,其实学过C语言,这个问题也不难想,因为foo这个局部变量是在栈上面分配的,而我们知道,函数在返回或退出的时候,这些局部变量就会自动被释放,所以返回给主函数的还是一个野指针。这里我们需要知道的另一个知识点就是,每个线程之间的栈是相互独立的,每个线程都拥有自己的栈区,虽然说它们的栈都是从进程空间的栈中分配的并且共享进程的栈,但是在创建线程的时候,每个线程都从进程栈区那儿获得一个私有的栈区。
处理上面的出现的问题办法就是,使用全局结构或malloc动态分配内存;
下面是我改为全局变量的例子:

点击(此处)折叠或打开

  1. #include<stdio.h>
  2. #include<pthread.h>
  3. #include<unistd.h>
  4. #include<stdlib.h>
  5. struct foo{
  6.     int a,b,c,d;
  7. };
  8. struct foo foo={1,2,3,4};
  9. void printfoo(const char *s,const struct foo *fp)
  10. {
  11.     printf("s is %s\n",s);
  12.     printf("structure at 0x%x\n",(unsigned)fp);
  13.     printf("foo.a=%d\n",fp->a);
  14.     printf("foo.b=%d\n",fp->b);
  15.     printf("foo.c=%d\n",fp->c);
  16.     printf("foo.d=%d\n",fp->d);
  17. }
  18. void *thr_fn1(void *arg)
  19. {
  20. //    struct foo foo={1,2,3,4};
  21.     printfoo("thread 1:\n",&foo);

  22.     pthread_exit((void *)&foo);
  23. }
  24. void * thr_fn2(void *arg)
  25. {
  26.     
  27.     printf("thread 2:ID is %d\n",pthread_self());
  28.     pthread_exit((void *)0);
  29. }
  30. int main(void)
  31. {
  32.     
  33.     int err;
  34.     pthread_t tid1,tid2;
  35.     struct foo *fp;
  36.     err=pthread_create(&tid1,NULL,thr_fn1,NULL);
  37.     if(err!=0){
  38.     
  39.         printf("create thread 1 is failed\n",strerror(err));
  40.         exit(1);
  41.     }
  42.     err=pthread_join(tid1,(void *)&fp);
  43.     if(err!=0)
  44.             printf("can't join thread1\n");
  45.     sleep(1);
  46.     err=pthread_create(&tid2,NULL,thr_fn2,NULL);
  47.     if(err!=0)
  48.     {
  49.         printf("create thread 2 is failed\n");
  50.          exit(1);
  51.     }
  52.     sleep(1);
  53.     printfoo("parent :\n",fp);
  54.     exit(0);
  55. }
运行结果如下所示:
s is thread 1:

structure at 0x804a034
foo.a=1
foo.b=2
foo.c=3
foo.d=4
thread 2:ID is -1218634896
s is parent :

structure at 0x804a034
foo.a=1
foo.b=2
foo.c=3
foo.d=4
不是就好了么,那么动态分配了,我相信学过C 的人都会,下去自己体验一下吧!其实还有一种方法就是在每个线程里定义一个结构体变量也可以,但我们的主要目的是主线程希望得到子线程返回的值。所以在使用此函数时一定要注意!这里还有一个问题是,大家看到我打印出的线程2的ID是负数,其实是我打印的时候格式的问题,只要改为%u就行了!
阅读(19465) | 评论(1) | 转发(2) |
给主人留下些什么吧!~~

suiyuemanbu2014-11-05 18:49:13

很不错啊