嵌入式开发学习日志(linux系统编程--进程(3)——线程)Day29
Linux命令的补充
1、
一、线程
概念:
1、线程是轻量级进程,一般是一个进程中的多个任务。
2、进程是系统中最小的资源分配单位;
线程是系统中最小的执行单位。
特征
1、共享资源:
2、效率高 30%
3、三方库: pthread clone posix
4.、编写代码头文件: pthread.h
5、 编译代码加载库: gcc x.c -lpthread
扩:以lib开头 .so结尾的为动态库(在内核中),中间的pthread为库名。
优缺点
优点:比多进程节省资源,可以共享变量。
缺点:1.线程和进程相比,稳定性,稍微差些
2.线程的调试gdb,相对麻烦些,因为并发
二、线程与进程的区别(面问)
1、资源:
(1)线程比进程多了共享资源;
(2)线程又具有部分私有资源;
(3)进程间只有私有资源没有共享资源。
2、空间:
(1)进程空间独立(写时复制),不能直接通信;
(2)线程可以共享空间(栈区默认不共享),可以直接通信。
3、不同点:
(1)创建开销不一样,进程创建需要3G空间,线程创建只需要8M,线程并发度高于进
程;
(2)进程变量不共享;
(3)进程切换(复杂)需要的缓存空间多,线程切换栈区,PC指针也发生变化;
(4)进程可申请到硬件资源;
4、稳定性差异:
(1)线程稳定性差(其中一个线程崩溃或严重异常,进程直接结束);
(2)项目任务复杂,用进程做;简单小任务,用线程做;
5、共同点:都能并发。
6、考虑用线程还是进程的两个准则:
(1)稳定性;
(2)看资源够不够用(够用用线程)
三、多线程程序设计步骤
1、创建多线程(只要创建成功就启动了)
2、线程空间操作 (设计函数表达要干什么)
3、线程资源回收(栈区回收,默认进程结束栈区不释放)
注:
(1)进程中的第一个线程为主线程,主线程有且仅有一个,(主线程号和进程号一
致)其它次线程为平级关系;
(2)主线程不需创建,运行a.out就出来了,后调用函数创建其他空间,在进程空间新
开栈区(8M)。
四、关于线程的函数
创建多线程 ==》线程空间操作 ===》线程资源回收
1、创建多线程(pthread_create)
形式:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
功能:
该函数可以创建一个指定的线程;
参数:
【pthread_t *thread】:线程pid号(新线程的线程号 )
【const pthread_attr_t *attr】:线程的属性,默认常规NULL,
【void *(*start_routine) (void *)】:函数的名字,空类型,空参数的(回调函数)是线程的执行空间
【void *arg】:参数,(线程工作的时候需要外部传参时,如果不需要,传NULL)
返回值:成功 0;
失败 错误码;
eg:
注意:(1)一次pthread_create执行只能创建一个线程。
(2)每个进程至少有一个线程称为主线程。
(3)主线程退出则所有创建的子线程都退出。
(4)主线程必须有子线程同时运行才算多线程程序。
(5) 线程id是线程的唯一标识,是CPU维护的一组数字。
(6)pstree 查看系统中多线程的对应关系。
(7)多个子线程可以执行同一回调函数。
(8) ps -eLf 查看线程相关信息Low Weigth Process
(9) ps -eLo pid,ppid,lwp,stat,comm
2、获取线程号(pthread_self)
形式:
pthread_t pthread_self(void);
功能:
获取当前线程的线程id;
返回值:
成功 返回当前线程的线程id,返回值为unsigned long int类型; %lu
失败 -1;
3、strerror
形式:
char *strerror(int errnum);
功能:
(1)报错函数,用于线程报错(多为极端情况使用),也可调用perror()函数(大部分
情况使用)
(2)strerror(errno)中errno为错误码
eg:
4、线程的退出pthread_exit
形式:
void pthread_exit(void *retval);
参数:
若没有返回的值,则传NULL;
线程退出时候的返回状态,临死遗言。
功能:
自行退出==》自杀===》子线程自己退出
子线程自己退出;
等价关系:
pthread_exit(NULL);
return (NULL);
eg:
5、线程的退出pthread_cancel;
形式:
int pthread_cancel(pthread_t thread);
参数:
【pthread_t thread】:将要结束的子线程线程号;
功能:
强制退出===》他杀====》主线程结束子线程;
返回值:
成功 0
失败 -1
注意:
只能是主线程去结束子线程;
eg:
五、线程的回收
线程的回收机制 ====》不同与进程没有孤儿线程和僵尸线程。
====》主线程结束任意生成的子线程都会结束。
====》子线程的结束不会影响主线程的运行。
关于线程的回收的函数
1、pthread_join
形式:
int pthread_join(pthread_t thread, void **retval);
参数:
【pthread_t thread】:回收线程的ID号;
【void **retval】:要回收的子线程返回值/状态。==》ptread_exit(值);
功能:
通过该函数的可以将指定的线程资源回收,该函数具有阻塞等待功能,如果指定的线程未结束,则回收的线程会阻塞;
返回值:
成功 0
失败 -1;
子线程的回收策略:
1、如果预估子线程可以有限范围内结束则正常用pthread_join等待回收。
2、如果预估子线程可能休眠或者阻塞则等待一定时间后强制回收。
3、如果子线程已知必须长时间运行,则不再回收其资源。
eg:(1)用函数pthread_join不传参
(2)用函数pthread_join传参
六、设置分离属性
目的:线程消亡,自动回收空间。
1、pthread_attr_init()
(1)函数原型:int pthread_attr_init(pthread_attr_t *attr);
(2)功能:初始化一个attr的变量
(3)参数:attr,需要变量来接受初始值
(4)返回值:0 成功,非0 错误
2、pthread_attr_destroy()
(1)函数原型:int pthread_attr_destroy(pthread_attr_t *attr);
(2)功能:销毁attr变量
(3)参数:attr,属性变量
(4)返回值:0 成功,非0 错误
3、pthread_attr_setdetachstate()
(1)函数原型: int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate);
(2)功能:把一个线程设置成相应的属性
(3)参数:attr,属性变量,有init函数初始化他。
detachstate:有2个可选值,
PTHREAD_CREATE_DETACHED
4、pthread_deatch()
(1)函数原型:int pthread_deatch(pthread_t thread);
(2)功能:设置分离属性
(3)参数:线程id号,填自己的id线程清理函数
5、pthread_cleanup_push()
(1)函数原型:void pthread_cleanup_push(void (*routine)(void *), void *arg);
(2)功能:注册一个线程清理函数
(3)参数:routine,线程清理函数的入口
arg,清理函数的参数。
(4)返回值:无
6、pthread_cleanup_pop()
(1)函数原型:void pthread_cleanup_pop(int execute);
(2)功能:调用清理函数
(3)参数:execute,非0 执行清理函数
0 ,不执行清理
(4)返回值:无
注:pthread_cleanup_push与pthread_cleanup_pop函数需成对出现;