玳瑁的嵌入式日记D27-0827(线程)
getcwd
功能说明:
buf:用于存储当前工作目录路径的字符数组缓冲区size:缓冲区的大小(以字节为单位)- 函数返回值:成功时返回指向缓冲区的指针(即
buf),失败时返回NULL,并设置errno
char *getcwd(char *buf, size_t size);
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
// 定义缓冲区,通常 PATH_MAX 是系统定义的最大路径长度
char cwd[1024];
// 获取当前工作目录
if (getcwd(cwd, sizeof(cwd)) != NULL) {
printf("当前工作目录: %s\n", cwd);
} else {
perror("获取目录失败");
return 1;
}
return 0;
}

线程(Thread)
线程是进程内的一个执行单元,多个线程共享进程的资源,但拥有各自的执行栈和寄存器状态。
优点: 比多进程节省资源,可以共享变量。
概念:线程是轻量级进程,一般是一个进程中的多个任务。
进程是系统中最小的资源分配单位.
线程是系统中最小的执行单位。
特征:
1、共享资源
2、效率高 30%
3、三方库: pthread clone posix
3.1 编写代码头文件: pthread.h
3.2 编译代码加载库: -lpthread library
libpthread.so (库文件)
gcc 1.c -lpthread
缺点:
1,线程和进程相比,稳定性,稍微差些
2,线程的调试gdb,相对麻烦些。
区别
线程与进程区别:
资源:
线程比进程多了共享资源。 IPC
线程又具有部分私有资源。
进程间只有私有资源没有共享资源。
空间:
进程空间独立,不能直接通信。
线程可以共享空间,可以直接通信。
| 特性 | 进程 | 线程 |
|---|---|---|
| 资源分配 | 拥有独立的内存空间和资源 | 共享所属进程的资源 |
| 开销 | 创建和切换开销大 | 创建和切换开销小 |
| 通信 | 需要使用进程间通信 (IPC) 机制 | 可直接访问共享内存 |
| 独立性 | 相互独立,一个崩溃不影响其他 | 同属一个进程,一个崩溃可能影响整个进程 |
| 调度 | 由操作系统调度 | 由操作系统调度,但开销更小 |
适用场景
- 进程:适合需要完全隔离的任务,如运行不同的应用程序
- 线程:适合需要共享数据且通信频繁的任务,如一个应用程序的不同功能模块
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
// 线程函数
void *thread_function(void *arg) {
int thread_num = *(int *)arg;
for (int i = 0; i < 5; i++) {
printf("线程 %d: 计数 %d\n", thread_num, i);
sleep(1);
}
return NULL;
}
int main() {
pthread_t thread1, thread2;
int num1 = 1, num2 = 2;
// 创建线程
if (pthread_create(&thread1, NULL, thread_function, &num1) != 0) {
perror("创建线程1失败");
return 1;
}
if (pthread_create(&thread2, NULL, thread_function, &num2) != 0) {
perror("创建线程2失败");
return 1;
}
// 等待线程结束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("所有线程执行完毕\n");
return 0;
}
注意:一次pthread_create执行只能创建一个线程。
每个进程至少有一个线程称为主线程。
主线程退出 则所有创建的子线程都退出。
主线程必须有子线程同时运行才算多线程程序。
线程id是线程的唯一标识,是CPU维护的一组数字。
pstree 查看系统中多线程的对应关系。
多个子线程可以执行同一回调函数。
ps -eLf 查看线程相关信息Low Weigth Process
ps -eLo pid,ppid,lwp,stat,comm
pthread_t pthread_self(void); unsigned long int; %lu
功能:获取当前线程的线程id
参数:无
返回值:成功 返回当前线程的线程id
失败 -1;
练习题:
设计一个多线程程序,至少有三个子线程
每个线程执行不同的任务,并实时打印执行
过程,同时表明身份。

线程的退出
1: 自行退出 ==》 自杀 ==》 子线程自己退出
exit(1);
void pthread_exit(void *retval); exit return p;
功能:子线程自行退出
参数: retval 线程退出时候的返回状态,临死遗言。
返回值:无
2: 强制退出 ==》他杀 ==》主线程结束子线程
int pthread_cancel(pthread_t thread);
功能:请求结束一个线程
参数:thread 请求结束一个线程tid
返回值:成功 0
失败 -1;
线程的回收
1、线程的回收机制 ====》不同与进程没有孤儿线程和僵尸线程。
====》主线程结束任意生成的子线程都会结束。
====》子线程的结束不会影响主线程的运行。
char * retval ; retval++; 1
int * retval;
int pthread_join(pthread_t thread, void **retval);
功能:通过该函数可以将指定的线程资源回收,该函数具有阻塞等待功能,如果指定的线程没有结束,则回收线程会阻塞。
参数:thread 要回收的子线程tid
retval 要回收的子线程返回值/状态。 ==》ptread_exit(值);
返回值: 成功 0
失败 -1;
子线程的回收策略:
1、如果预估子线程可以有限范围内结束则正常用pthread_join等待回收。
2、如果预估子线程可能休眠或者阻塞则等待一定时间后强制回收。
3、如果子线程已知必须长时间运行则,不再回收其资源。

关于局部变量的解决,1.static
2.malloc (需要free)
atoi() atof()
线程的参数,返回值
1、传参数
传整数

传字符串
栈区字符数组:
字符串常量:
char *p = "hello";
堆区字符串;


传结构体
1、定义结构体类型
2、用结构体定义变量
3、向pthread_create传结构体变量
4、从fun子线程中获取结构体数据

设置分离属性
设置分离属性,目的线程消亡,自动回收空间。
attribute
int pthread_attr_init(pthread_attr_t *attr);
功能,初始化一个attr的变量
参数:attr,需要变量来接受初始值
返回:0 成功,
非0 错误;
int pthread_attr_destroy(pthread_attr_t *attr);
功能:销毁attr变量。
attr,属性变量
返回:0 成功,
非0 错误;
int pthread_deatch(pthread_t thread);
功能,设置分离属性 将指定的线程标记为 “分离状态”(detached state)。
参数,线程id号,填自己的id
注意:一旦线程被标记为分离状态,就不能再通过 pthread_join() 获取其返回值了。

void pthread_cleanup_push(void (*routine)(void *), void *arg);
功能:注册一个线程清理函数
参数,routine,线程清理函数的入口
arg,清理函数的参数。
返回值,无
void pthread_cleanup_pop(int execute);
功能:调用清理函数
execute,非0 执行清理函数
0 ,不执行清理
返回值,无



openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)