zoukankan      html  css  js  c++  java
  • Linux 下子线程 exit code 在主线程中的使用

    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 #include <stdio.h>
    15 #include <stdlib.h>
    16 #include <pthread.h>
    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: 100
    thread 1 exit code: 100
    thread 2 start:
    thread 2 exit code: SOT-363
    thread 2 exit code: SOT-363

    可以看到“直接使用指针方式” 和 “强制类型转换方式” 输出的结果都一样。

    上面的都是基本数据类型方式,那么再试一下其他的数据类型,例如结构体:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <pthread.h>
     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:  421127xxxx78455623
    In main thread:
        name:Lee
        age: 33
        sex: M
        ID:  421127xxxx78455623
    In main thread:
        name:Lee
        age: 33
        sex: M
        ID:  421127xxxx78455623
    thread 2 start:
    thread 2 exit code: SOT-363
    thread 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: 100
    sizeof tret is 8 Bytes
    sizeof(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 于公司。

  • 相关阅读:
    页面定制CSS代码
    记录-20190511
    Java集合
    EL表达式
    javabean
    写一篇博文介绍JSP
    编写一篇博文介绍COOKIE和Session的原理及异同
    过滤器的使用
    Java种的String
    Java包装类
  • 原文地址:https://www.cnblogs.com/LinTeX9527/p/4750083.html
Copyright © 2011-2022 走看看