linux线程posix实现方案
每个线程都有一个线程ID
c
/* 用于表示线程ID数据结构 */
pthread_t // 每个线程都有一个线程ID
/* 线程创建 */
pthread_create()
/*
__newthread:函数成功返回将ID存储在此变量中。
__attr:定制线程属性。
__start_routine:函数指针。
__arg:传递给函数的参数。
*/
int pthread_create (pthread_t *__restrict__newthread,
const pthread_attr_t *__restrict__attr,
void *(*__start_routine) (void *),
void *__restrict__arg);
新知识
man命令
在thread_posix.c中使用了exit(0)和abort(),一开始没有引入对应的头文件,就报错了,说这两个地方有问题。
可以在linux服务器中使用man exit和man abort来查看是哪个头文件,然后再引入即可。
man是一个用于查看系统手册页(manual pages)的命令,其名称来源于"manual"的缩写,作用是提供关于命令、函数、系统调用等的技术文档。
man的含义与作用
- 名称来源 :
man是"manual"的缩写,意为手册或指南。 - 作用 :
man命令用于查看Linux系统中各种命令、函数、系统调用等的手册页。这些手册页提供了详细的说明、用法示例、参数解释等信息,是开发者和管理员的重要参考资料。 - 使用方法 :在终端中输入
man命令,后跟要查询的命令、函数或系统调用的名称。例如,man ls用于查看ls命令的手册页,man abort用于查看abort函数的手册页。
ls -l
ruby
ZM10:/system/bin $ ls -l bootanimation
-rwxr-xr-x 1 root shell 23504 2026-03-21 16:07 bootanimationls
分析 ls -l命令的输出格式:
我来帮你详细分析 ls -l命令的输出格式,一次教会你!
1. 整体输出结构
diff
-rwxr-xr-x 1 root shell 23504 2026-03-21 16:07 bootanimation
这是一个完整的文件信息行,共7个字段。
2. 各字段详解(从左到右)
字段1:文件类型和权限 (-rwxr-xr-x)
第1个字符:文件类型
-= 普通文件
d= 目录
l= 符号链接
b= 块设备文件
c= 字符设备文件
第2-10个字符:权限(每3位一组)
第2-4位:所有者权限(u = user)
第5-7位:所属组权限(g = group)
第8-10位:其他人权限(o = others)
权限字符含义:
r= 读权限
w= 写权限
x= 执行权限
-= 无对应权限
字段2:硬链接数 (1)
表示该文件有多少个硬链接
目录至少为2(.和 ..)
字段3:所有者 (root)
文件的所有者用户
字段4:所属组 (shell)
文件所属的用户组
3. 实战分析示例
diff
-rwxr-xr-x 1 root shell 23504 2026-03-21 16:07 bootanimation
分析结果:
这是一个普通文件
权限:所有者(root)可读、写、执行;组成员可读、执行;其他人可读、执行
有 1个 硬链接
所有者是 root 用户
所属组是 shell 组
文件大小为 23504字节(约23KB)
最后修改于 2026年3月21日 16:07
文件名为 bootanimation
安卓封装的Thread类
Android native的Thread类是Android提供的一个基础类,源码路径: system\core\libutils\include\utils\Thread.h system\core\libutils\Threads.cpp
安卓封装的Thread类使用了linux线程posix的实现方案。
在Thread.h中可以看到,Thread继承了 RefBase 类,而本身继承于RefBase,所以具有RefBase相应的一些特性。
cpp
system\core\libutils\include\utils\Thread.h
class Thread : virtual public RefBase
而在system/core/libutils/include/utils/RefBase.h中,有一个方法onFirstRef(),根据注释,创建之后就会被调用:
cpp
system/core/libutils/include/utils/RefBase.h
class RefBase {
// Invoked after creation of initial strong pointer/reference.
virtual void onFirstRef();
Thread类的执行流程
线程创建并启动运行,通过run方法
cpp
virtual status_t run( const char* name,
int32_t priority = PRIORITY_DEFAULT,
size_t stack = 0);
cpp
/* 首先看run方法,通常走else分支,调用了androidCreateRawThreadEtc
*/
status_t Thread::run(const char* name, int32_t priority, size_t stack)
{
...
bool res;
if (mCanCallJava) {
res = createThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
} else {
res = androidCreateRawThreadEtc(_threadLoop,
this, name, priority, stack, &mThread);
}
}
int androidCreateRawThreadEtc(android_thread_func_t entryFunction,
void *userData,
const char* threadName __android_unused,
int32_t threadPriority,
size_t threadStackSize,
android_thread_id_t *threadId)
{
// 这里可以看到pthread_attr_t,就是之前提到的linux的线程属性
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
...
errno = 0;
pthread_t thread; //之前在linux属性中提到的,用于表示线程ID数据结构
// 这里的pthread_create,更是之前提到的linux中创建线程的方法,而其中的entryFunction,就是线程创建后要执行的方法,而根据之前传入的参数,entryFunction就是_threadLoop
int result = pthread_create(&thread, &attr,
(android_pthread_entry)entryFunction, userData);
pthread_attr_destroy(&attr);
...
}
/*
该函数主要通过调用threadLoop()函数,作为线程执行函数,它是有返回值的方法,而且_threadLoop会根据返回值确定是否继续循环执行的方法,因此基类必要要实现threadLoop函数。
*/
int Thread::_threadLoop(void* user)
{
...
bool first = true;
do {
bool result;
// 第一次时first = true一定会走if分支
if (first) {
first = false;
// 先执行readyToRun,在threadLoop之前
self->mStatus = self->readyToRun();
result = (self->mStatus == OK);
if (result && !self->exitPending()) {
// 然后进入这个if分支,threadLoop()返回结果给result,决定是否退出loop循环,result为true,这个do while循环就会继续
result = self->threadLoop();
}
} else {
//do while循环的第二次、第三次后续都走这个分支,都会执行threadLoop()
result = self->threadLoop();
}
// establish a scope for mLock
{
Mutex::Autolock _l(self->mLock);
// 当result == false时会进入触发break,退出loop循环。或者mExitPending为true也会触发,销毁线程时调用requestExit()函数,requestExit()就会把mExitPending置位true
if (result == false || self->mExitPending) {
self->mExitPending = true;
self->mRunning = false;
...
break;
}
}
// Release our strong reference, to let a chance to the thread
// to die a peaceful death.
strong.clear();
// And immediately, re-acquire a strong reference for the next loop
strong = weak.promote();
} while(strong != nullptr);
return 0;
}
线程请求退出方法: 线程销毁,子类最好通过实现requestExit()函数,首先调用Thread类的requestExit()函数,将线程状态mExitPending置为true,然后中断threadLoop,结合前面_threadLoop的do while循环结束条件就知道,退出_threadLoop循环只有两种,要么threadLoop()返回true,要么mExitPending = true:
cpp
void Thread::requestExit()
{
Mutex::Autolock _l(mLock);
mExitPending = true;
}
安卓native堆栈打印
1、进入对应的cpp文件,放开#define LOG_NDEBUG 0注释,且变成#define LOG_NDEBUG 1
2、声明头文件
cpp
#include<utils/CallStack.h>
#include<utils/Log.h>
3、调用方法:
cpp
CallStack stack;
stack.update();
stack.log("BootAnimation: movie");
4、mk或者bp中需要链接以下so库:
libutils
libcutils
如果加了上面两个so库,编译还是报错,就再加上 libutilscallstack ,我只加libcutils和libutils编译就会报错,再加上 libutilscallstack 就好了。
cpp
frameworks/base/cmds/bootanimation/BootAnimation.cpp
bool BootAnimation::movie() {
ATRACE_CALL();
// 以下是新加的堆栈log
ALOGD("[cmy] BootAnimation: movie start");
CallStack stack;
stack.update();
stack.log("BootAnimation: movie");
if (mAnimation == nullptr) {
mAnimation = loadAnimation(mZipFileName);
}
if (mAnimation == nullptr)
return false;
......
log
打印的堆栈log
03-14 10:38:45.257 4450 4453 D BootAnimation: [cmy] BootAnimation: movie start
03-14 10:38:45.266 4450 4453 D BootAnimation: movie: #00 pc 000000000000fab0 /system/lib64/libbootanimation.so (android::BootAnimation::movie()+112) (BuildId: 2cc5e488eba01c1dfdaa739a3a748677)
03-14 10:38:45.266 4450 4453 D BootAnimation: movie: #01 pc 000000000000f4bc /system/lib64/libbootanimation.so (android::BootAnimation::threadLoop()+272) (BuildId: 2cc5e488eba01c1dfdaa739a3a748677)
03-14 10:38:45.266 4450 4453 D BootAnimation: movie: #02 pc 000000000001003c /system/lib64/libutils.so (android::Thread::_threadLoop(void*)+416) (BuildId: 974f050a274d2b06051a6a711d1870ac)
根据上方三条native堆栈log,调用顺序是Thread::_threadLoop -> BootAnimation::threadLoop() ->BootAnimation::movie()
但是native堆栈log并不能具体到某一行。
03-14 10:38:45.266 4450 4453 D BootAnimation: movie: #03 pc 000000000006d8d0 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+196) (BuildId: 64eb5106bc8ae51d575bce9d5c64cec5)
03-14 10:38:45.266 4450 4453 D BootAnimation: movie: #04 pc 000000000005fd34 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+68) (BuildId: 64eb5106bc8ae51d575bce9d5c64cec5)