Linux线程函数原型是这样的:
1 void* thread_fun(void* arg)
它的返回值是 空类型指针,入口参数也是 空类型指针。那么线程的 exit code 也应该是 void * 类型的。但是在主线程怎么捕获子线程的 exit code 并使用的呢?
捕获的思路如下:
1. 在主线程中定义一个 void* tret;
2. 使用 pthread_join(tidxx, &tret);
这样就能够捕获到子线程的 exit code。
但是如何使用呢?这就取决于子线程中的 exit code 具体表示的数据类型了,可以是 int, char *, struct xxxStr 等等,然后直接在主线程中使用类型转换到对应的数据类型就行了。
例如:
1 /**************************************************************** 2 # File Name: thread_cleanup2.c 3 # Author : lintex9527 4 # E-Mail : lintex9527@yeah.net 5 # Created Time: Sat 22 Aug 2015 11:01:59 AM HKT 6 # Purpose : 7 # Outline : 8 # Usage : 9 # --------------------------------------------------10 # Result : 11 # --------------------------------------------------12 *****************************************************************/13 14 #include15 #include 16 #include 17 18 void* thr_fn01(void *arg)19 {20 printf("thread 1 start:\n");21 pthread_exit((void *)100);22 pthread_exit((void *)"SOT-26"); // the first pthread_exit() works, the rest below that does not execute.23 }24 25 void* thr_fn02(void *arg)26 {27 printf("thread 2 start:\n"); 28 pthread_exit((void *)"SOT-363");29 }30 31 int main(void)32 {33 int err;34 pthread_t tid1, tid2;35 void *tret;36 37 pthread_create(&tid1, NULL, thr_fn01, (void *)1);38 pthread_join(tid1, &tret);39 printf("thread 1 exit code: %d\n", (tret));40 printf("thread 1 exit code: %d\n", (int *)(tret));41 42 pthread_create(&tid2, NULL, thr_fn02, (void *)1);43 pthread_join(tid2, &tret);44 printf("thread 2 exit code: %s\n", (tret));45 printf("thread 2 exit code: %s\n", (char *)(tret));46 47 return 0;48 }
执行的结果如下:
$ ./thread_cleanup2.exe thread 1 start:thread 1 exit code: 100thread 1 exit code: 100thread 2 start:thread 2 exit code: SOT-363thread 2 exit code: SOT-363
可以看到“直接使用指针方式” 和 “强制类型转换方式” 输出的结果都一样。
上面的都是基本数据类型方式,那么再试一下其他的数据类型,例如结构体:
1 #include2 #include 3 #include 4 #include 5 6 7 struct personStr{ 8 char name[30]; 9 unsigned int age;10 char sex; // 'M', 'W'11 char ID[30];12 };13 14 void printPerson(const char * str, struct personStr *p)15 {16 printf("%s\n", str);17 printf(" name:%s\n", p->name);18 printf(" age: %d\n", p->age);19 printf(" sex: %c\n", p->sex);20 printf(" ID: %s\n", p->ID);21 }22 23 struct personStr thisman;24 25 void* thr_fn01(void *arg)26 {27 printf("thread 1 start:\n");28 memcpy(thisman.name, "Lee", strlen("Lee"));29 thisman.age = 33;30 thisman.sex = 'M';31 memcpy(thisman.ID, "421127xxxx78455623", strlen("421127xxxx78455623"));32 printPerson("In pthread 1:", &thisman);33 34 pthread_exit((void *)&thisman); 35 }36 37 void* thr_fn02(void *arg)38 {39 printf("thread 2 start:\n");40 pthread_exit((void *)"SOT-363");41 42 }43 44 int main(void)45 {46 int err;47 pthread_t tid1, tid2;48 void *tret;49 50 err = pthread_create(&tid1, NULL, thr_fn01, (void *)1);51 pthread_join(tid1, &tret);52 printPerson("In main thread:", tret); // 直接使用指针53 printPerson("In main thread:", (struct personStr *)tret); // 强制类型转换为结构体指针54 55 err = pthread_create(&tid2, NULL, thr_fn02, (void *)1);56 pthread_join(tid2, &tret);57 printf("thread 2 exit code: %s\n", (tret));58 printf("thread 2 exit code: %s\n", (char *)(tret));59 60 return 0;61 }
执行结果如下:
$ ./thread_cleanup2.exe thread 1 start:In pthread 1: name:Lee age: 33 sex: M ID: 421127xxxx78455623In main thread: name:Lee age: 33 sex: M ID: 421127xxxx78455623In main thread: name:Lee age: 33 sex: M ID: 421127xxxx78455623thread 2 start:thread 2 exit code: SOT-363thread 2 exit code: SOT-363
可以看到 “直接使用指针” 和 “强制类型转换”结果都是一样的。如果图方便就直接使用指针,而且这样的代码通用性也好,万一将来某天结构体名字变动了,就需要改动很多地方了,但是也有弊病,就是代码的易读性不好。
有一点奇怪的就是第一个例子中,为什么返回的是整数 int 类型的"100",却能通过指针打印出"100"呢?
这样验证:
printf("thread 1 exit code: %d\nsizeof tret is %d Bytes\nsizeof(int) is %d Bytes.\n", (tret), sizeof(tret), sizeof(int));
结果是这样的:
thread 1 exit code: 100sizeof tret is 8 Bytessizeof(int) is 4 Bytes.
那么就说明 tret 的确是指针类型的,占用了8个字节的数据,而 int 类型的数据只占用了4个字节,而且进行如下的尝试,编译失败了:
printf("tret * 3 = %d\n", tret * 3);很不幸,失败了,结果:thread_cleanup2.c:93: error: invalid operands to binary * (have ‘void *’ and ‘int’)make: *** [thread_cleanup2.o] Error 1
如果的确是想使用 tret 的值100, 可否通过指针取值运算呢?
printf("tret * 3 = %d\n", (*((int *)tret)) * 3);很不幸,这样也失败了。
如果要想把返回值 tret 参与其他的运算,就必须使用一个转换的桥梁。利用 “中间变量 = tret”,然后使用这个中间变量,虽然编译会有 warning 提醒,但是的确能使用:
//printf("tret * 3 = %d\n", (*((int *)tret)) * 3);// failed.//int num = *((int *)tret); // failed.int num = tret; printf("num = %d, num * 3 = %d\n", num, num * 3 ); 编译提示: thread_cleanup2.c:95: warning: initialization makes integer from pointer without a cast cc -o thread_cleanup2.exe thread_cleanup2.o -lpthread 运行结果: thread 1 exit code: 100 sizeof tret is 8 Bytes sizeof(int) is 4 Bytes. num = 100, num * 3 = 30
2015-08-22 13:17:12 于公司。