Linux 下子线程 exit code 在主线程中的使用
Linux线程函数原型是这样的:
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 等等,然后直接在主线程中使用类型转换到对应的数据类型就行了。
例如:
/****************************************************************
# File Name: thread_cleanup2.c
# Author : lintex9527
# E-Mail : lintex9527@yeah.net
# Created Time: Sat 22 Aug 2015 11:01:59 AM HKT
# Purpose :
# Outline :
# Usage :
# --------------------------------------------------
# Result :
# --------------------------------------------------
*****************************************************************/ #include <stdio.h>
#include <stdlib.h>
#include <pthread.h> void* thr_fn01(void *arg)
{
printf("thread 1 start:\n");
pthread_exit((void *));
pthread_exit((void *)"SOT-26"); // the first pthread_exit() works, the rest below that does not execute.
} void* thr_fn02(void *arg)
{
printf("thread 2 start:\n");
pthread_exit((void *)"SOT-363");
} int main(void)
{
int err;
pthread_t tid1, tid2;
void *tret; pthread_create(&tid1, NULL, thr_fn01, (void *));
pthread_join(tid1, &tret);
printf("thread 1 exit code: %d\n", (tret));
printf("thread 1 exit code: %d\n", (int *)(tret)); pthread_create(&tid2, NULL, thr_fn02, (void *));
pthread_join(tid2, &tret);
printf("thread 2 exit code: %s\n", (tret));
printf("thread 2 exit code: %s\n", (char *)(tret)); return ;
}
执行的结果如下:
$ ./thread_cleanup2.exe
thread start:
thread exit code:
thread exit code:
thread start:
thread exit code: SOT-
thread exit code: SOT-
可以看到“直接使用指针方式” 和 “强制类型转换方式” 输出的结果都一样。
上面的都是基本数据类型方式,那么再试一下其他的数据类型,例如结构体:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h> struct personStr{
char name[];
unsigned int age;
char sex; // 'M', 'W'
char ID[];
}; void printPerson(const char * str, struct personStr *p)
{
printf("%s\n", str);
printf(" name:%s\n", p->name);
printf(" age: %d\n", p->age);
printf(" sex: %c\n", p->sex);
printf(" ID: %s\n", p->ID);
} struct personStr thisman; void* thr_fn01(void *arg)
{
printf("thread 1 start:\n");
memcpy(thisman.name, "Lee", strlen("Lee"));
thisman.age = ;
thisman.sex = 'M';
memcpy(thisman.ID, "421127xxxx78455623", strlen("421127xxxx78455623"));
printPerson("In pthread 1:", &thisman); pthread_exit((void *)&thisman);
} void* thr_fn02(void *arg)
{
printf("thread 2 start:\n");
pthread_exit((void *)"SOT-363"); } int main(void)
{
int err;
pthread_t tid1, tid2;
void *tret; err = pthread_create(&tid1, NULL, thr_fn01, (void *));
pthread_join(tid1, &tret);
printPerson("In main thread:", tret); // 直接使用指针
printPerson("In main thread:", (struct personStr *)tret); // 强制类型转换为结构体指针 err = pthread_create(&tid2, NULL, thr_fn02, (void *));
pthread_join(tid2, &tret);
printf("thread 2 exit code: %s\n", (tret));
printf("thread 2 exit code: %s\n", (char *)(tret)); return ;
}
执行结果如下:
$ ./thread_cleanup2.exe
thread start:
In pthread :
name:Lee
age:
sex: M
ID: 421127xxxx78455623
In main thread:
name:Lee
age:
sex: M
ID: 421127xxxx78455623
In main thread:
name:Lee
age:
sex: M
ID: 421127xxxx78455623
thread start:
thread exit code: SOT-
thread exit code: SOT-
可以看到 “直接使用指针” 和 “强制类型转换”结果都是一样的。如果图方便就直接使用指针,而且这样的代码通用性也好,万一将来某天结构体名字变动了,就需要改动很多地方了,但是也有弊病,就是代码的易读性不好。
有一点奇怪的就是第一个例子中,为什么返回的是整数 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 exit code:
sizeof tret is Bytes
sizeof(int) is Bytes.
那么就说明 tret 的确是指针类型的,占用了8个字节的数据,而 int 类型的数据只占用了4个字节,而且进行如下的尝试,编译失败了:
printf("tret * 3 = %d\n", tret * );
很不幸,失败了,结果:
thread_cleanup2.c:: error: invalid operands to binary * (have ‘void *’ and ‘int’)
make: *** [thread_cleanup2.o] Error
如果的确是想使用 tret 的值100, 可否通过指针取值运算呢?
printf("tret * 3 = %d\n", (*((int *)tret)) * ); 很不幸,这样也失败了。
如果要想把返回值 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 * ); 编译提示:
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 于公司。
Linux 下子线程 exit code 在主线程中的使用的更多相关文章
- 开子线程下载图片,回到主线程刷新UI步骤
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [NSThread detachN ...
- 用Handler的post()方法来传递线程中的代码段到主线程中执行
自定义的线程中是不能更新UI的,但是如果遇到更新UI的事情,我们可以用handler的post()方法来将更新UI的方法体,直接传送到主线程中,这样就能直接更新UI了.Handler的post()方法 ...
- android4.0以上访问网络不能在主线程中进行以及在线程中操作UI的解决方法
MONO 调用一个线程操作UI 然后报Only the original thread that created a view hierarchy can touch its views.错误 goo ...
- Android中,子线程使用主线程中的组件出现问题的解决方法
Android中,主线程中的组件,不能被子线程调用,否则就会出现异常. 这里所使用的方法就是利用Handler类中的Callback(),接受线程中的Message类发来的消息,然后把所要在线程中执行 ...
- Java线程和多线程(四)——主线程中的异常
作为Java的开发者,在运行程序的时候会碰到主线程抛异常的情况.如果开发者使用Java的IDE比如Eclipse或者Intellij IDEA的话,可能是不需要直接面对这个问提的,因为IDE会处理运行 ...
- [原]unity中WWW isDone方法只能在主线程中调用
项目中要使用动态加载,原计划是生成WWW对象后,放到一个容器里.由一个独立线程轮询容器里的对象,如果www.isDone为true时,回调一个接口把结果交给请求方. new Thread( new T ...
- 主线程中也不绝对安全的 UI 操作
从最初开始学习 iOS 的时候,我们就被告知 UI 操作一定要放在主线程进行.这是因为 UIKit 的方法不是线程安全的,保证线程安全需要极大的开销.那么问题来了,在主线程中进行 UI 操作一定是安全 ...
- 在主线程中慎用WaitForSingleObject (WaitForMultipleObjects)
下面的代码我调试了将近一个星期,你能够看出什么地方出了问题吗?线程函数: DWORD WINAPI ThreadProc( while(!bTerminate) { // 从 ...
- httpUrlConnection连接网络的用法(用到了handle传递消息,在主线程中更新UI)
由于httpclient在Android5.0以后已经过时,所以官方推荐使用httpUrlConnection来连接网络,现将该连接的基本方法展示,如下 注意:记得加入<uses-permiss ...
随机推荐
- 使用C#开发屏幕保护程序步骤
本文介绍使用C#制作屏幕保护的方法,这个屏幕保护就是仿效视窗系统自带的字幕屏保. 屏幕保护程序的扩展名虽然是"scr",但其实是一个可执行的"exe"文件.但他 ...
- jQuery实现隐藏标签
要求:用户进入该页面时,品牌列表默认是精简显示,用户可以单击商品列表下方的“显示全部品牌”按钮来显示全部的品牌. <%@ Page Language="C#" Inherit ...
- 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock
[源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...
- python,python3
当下主流的Linux发行版都集成了python2,直接在终端输入$python就可进入交互式解释器,或者输入$python3进入python3的解释器,当然,也可以使用这个解释器直接翻译一个pytho ...
- Tomcat配置文件server.xml
Tomcat目录中的server.xml配置文件 server.xml称为主配置文件或全局配置文件 它完成以下两个目标: 1,提供Tomcat组件的初始化配置 2,说明Tomcat的结构和含义,使得T ...
- web技术人员-推荐书籍
学习是技术人员成长的基础,本次分享20本技术方面的书籍,这些书不是每一本都是经典,但是每一本都有其特点.以下20本大部分本人都看过,因此推荐给大家.(本次推荐的20本只是一个参考,比如像Head Fi ...
- mybatis中#和$符号的区别
mybatis做为一个轻量级ORM框架在许多项目中使用,因其简单的入门受到了广大开发者的热爱.在近期项目中再做一个相关的开发,碰到了#.$符号这样的问题,之前没怎么注意过,通过学习之后,有了点感悟,分 ...
- HTML5中的音视频处理
* 音视频处理 * 视频处理 * 基本内容 * 使用Flash技术处理HTML页面中的视频内容 * 包含音频.动画.网页游戏等 * 特点 * 浏览器原生不支持(IE浏览器要求安装ActiveX组件) ...
- 移动端H5---页面适配问题详谈(一)
一.前言 昨天唠叨了哈没用的,今天说点有用的把.先说一下响应式布局吧,我一直认为响应式布局的分项目,一下布局简单得项目做响应式还是可以可以得.例如博客.后台管理系统等.但是有些会认为响应式很牛逼,尤其 ...
- 一道灵活的css笔试题
今天在网上看到一css笔试题,乍一看很简单,实则内部暗藏玄机,题目大概是:九宫格,每格长宽50px,边框宽度5px,鼠标经过边框变红,效果如下: 鼠标路过时: 以下是代码(如有不足之处望多加指正) & ...