linux下的多线程
多线程:包括线程概念/线程控制/线程安全/线程基本应用
多任务处理:多创建几个进程,一个进程就有一个pcb,能够串行化的完成一个任务,在一个进程中多创建几个pcb,pcb是调度程序运行的描述,有多少个pcb就有多少个执行流程,
什么是线程?
线程是一个进程内部的控制序列,线程是进程中的一条执行流,在linux下通过pcb实现,因此实际上linux下的线程就是一个pcb,并且linux下的pcb共用一个虚拟地址空间,相较于传统pcb更加轻量化,也被称之为轻量级进程。
多线程是同时处理,只有一个虚拟地址空间,多进程各有各的虚拟地址空间和执行代码段。
进程是操作系统资源分配的基本单位;(操作系统会为一个程序的运行分配所需的所有资源)
线程是cpu调度的基本单位。
linux下的进程其实是一个线程组,一个进程中可以有多个线程(多个pcb),线程是进程中的一条执行流。一个进程中至少会有一个线程。
创建线程会伴随在内核中创建一个pcb来实现程序的调度,作为进程中的一条执行流。
进程就是多个线程的一个合集,并且这个进程中的所有pcb共用进程中的大部分资源(程序运行时,操作系统为程序运行所分配的所有资源)。
线程之间的独有与共享:
独有:标识符,寄存器,信号屏蔽字,优先级。
共享:虚拟地址空间(代码段/数据段),文件描述符表(IO信息),信号处理的回调函数(SIG_IGN忽略、SIG_DFL默认或自定义),当前工作目录,用户id和组id。
为什么信号是先注销,再处理?
信号时针对整个进程通知事件进行处理的,但是一个信号只需要被处理一次就够了,然而一个进程会有多个执行流,到底谁处理这个事件(谁拿到时间片,谁就能处理),有的线程不希望操作被打断,就可以屏蔽这个信号。
使用vfork创建一个子进程;父子进程共用同一个虚拟地址空间,但是父进程会阻塞(父进程阻塞的原因是防止调用栈紊乱,数据紊乱)直到子进程exit或者程序替换;
fork(写时拷贝,修改的时候开辟空间)不仅会创建pcb还会为pcb创建虚拟地址空间,创建页表,因此fork后父子进程数据独有(各有各的虚拟地址空间,若数据发生改变映射后指向不同的物理内存区域),代码共享的。
fork完虚拟地址空间是立即创建的,物理内存没有立即创建,而是数据发生改变时(是改变页表映射)才会重新开辟,拷贝数据过来。
创建线程是创建一个pcb,然后通过指针指向同一个虚拟地址空间,映射的也是同一块物理内存。
多线程:多个pcb作为独立执行流肯定是同时运行,如何做到不会调用栈混乱
errno:系统调用完毕后重置的一个全局变量。
多线程/多进程进行多任务处理的优缺点分析:
多线程的优点:
1.线程间通信更加灵活方便(除了进程间通信方式之外还有全局变量以及函数传参)--共用同一个虚拟地址空间,只要知道地址就能访问同一块空间)
2.线程的创建与销毁成本更低(创建线程创建一个pcb,共用的数据只需要使用一个指针指向同一处就可以)
3.同一个进程中的线程间调度成本更低(调度切换需要切换页表...)
多进程的优点:
1.多进程的健壮性,稳定性更高(异常以及一些系统调用exit直接针对整个进程生效)
共同的优点:等待+数据拷贝
1.IO密集型程序:多任务并行处理,对cpu要求并不高,执行流个数没有要求(多磁盘可以实现同时处理)
2.CPU密集型程序:程序中进行大量数据运算处理;cpu资源足够,就可以同时处理,提高效率 (通常执行流的个数是cpu核心数+1)
创建线程很多的话,而cpu资源不够多,会造成大量的进程切换调度成本提高
线程控制:通过代码实现线程的创建/退出/等待/分离
线程控制的代码都是库函数,有封装的线程库函数。使用库函数创建一个线程,本质是在内核中创建一个轻量级进程实现程序调度。
线程创建-创建一个新的线程:
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *
(*start_routine)(void*), void *arg);
thread:输出型参数,用于获取线程ID--线程的操作句柄
attr:设置线程的属性,attr为NULL表示使用默认属性
start_routine:是个函数指针,线程启动后要执行的函数,运行完毕,线程退出
arg: 传给线程启动函数的参数
返回值:成功返回0;失败返回错误码(非0)
声明和定义的区别就是有无实现。
未声明:不知道这个函数或变量,从来没有。(通常是没有添加头文件)
未定义:只是不知道这个函数或变量的空间和实现在哪里。(没有把库添加上)
线程创建代码如下:
tid是一个无符号长整形数据,一个线程就有一个pcb,每个pcb都有一个pid--pid是一个整形数据。
tid和pid有什么联系?
pid--是一个轻量级进程id,是内核中task_struct结构体中的id。
tid---是一个线程id,线程的操作句柄,这个tid是用户态线程的id,是线程独有的这块空间的首地址,每个线程被创建出来之后,都会开辟一块空间,存储自己的栈,自己的描述信息。
ps -ef|grep create 看到的进程信息中的pid到底是哪个pcb的pid?
task_struct-->pid:轻量级进程id,也就是ps -ef看到的LWP
task_struct-->tgid:线程组id,等于主线程id (也就是外边所看到的进程id)
LWP和tgid实际上几乎用不到,因为线程的操作都是通过tid完成的。
结果如下:
库的链接使用:
whereis libpthread.so可以查看库的位置。
1.将库文件放在指定的路径下 /lib64 /usr/lib64
2.将库文件路径添加到环境变量 LIBRARY_PATH中。
3.使用gcc -L选项指定库文件所在路径。
4.gcc默认链接动态库,动态库也可以使用-L指定库路径,-l指定库名称
线程终止--线程退出--如何退出一个线程?
线程入口函数运行完毕,线程就会自动退出--在线程入口函数中调用return(但main函数中return退出的是进程而不是主线程)
结果可以看到普通线程只运行了一次 就退出,而主线程没有退出。
void pthread_exit(void *retval); 退出线程接口--谁调用谁退出,retval是退出返回值。
但是exit无论在哪都是进程退出。
代码如下:
结果如下:
发现主线程退出了,普通线程还依然在打印。通过查看进程发现,有2个exit,第一个为僵尸状态-僵尸进程,第二个为休眠状态。
主线程退出,并不会导致进程退出,只有所有的线程都退出了,进程才会退出。
int pthread_cancel(pthread_t thread);取消一个线程;退出的线程被动取消的。
线程等待:等待一个线程的退出,获取退出线程的返回值,回收线程所占的资源
线程有一个属性,默认创建出来这个属性是joinable,处于这个属性的线程,退出后,需要被其他线程等待获取返回值回收资源。
int pthread_join(pthread_t thread, void **retval);--等待指定线程退出,获取其返回值
thread:要等待退出的线程tid
retval:输出型参数,用于返回线程的返回值。
线程的返回值是一个void*,是一个一级指针。若要通过一个函数的参数获取一级指针,就需要传入一个一级指针变量的地址进来。
常量与普通变量的区别--存储位置不同,生命周期不同。
默认情况下,一个线程必须被等待,若不等待,则会造成资源泄露。
线程分离:将线程joinable属性修改为detach属性
一个线程属性若是joinable那么就必须被等待
一个线程属性若是detach那么这个线程退出后则自动释放资源,不需要被等待(因为资源已经自动被释放了)
为什么要分离线程?
分离一个线程,一定是对线程的返回值不感兴趣,根本不想获取,又不想一直等待线程退出,这种情况才会分离线程。
int pthread_detach(pthread_t thread);--将指定的线程分离出去--属性修改为detach
pthread_detach(pthread_self());--返回调用线程的tid,自己分离自己,实际就是设置一个属性。
分离线程,只是说线程退出后自动释放资源。
linux下的多线程相关推荐
- Linux下的多线程编程
1 引言 线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者.传统的Unix也支持线程的概念,但是在一个进程(process ...
- [原创]手把手教你Linux下的多线程设计--Linux下多线程编程详解(一)
本文可任意转载,但必须注明作者和出处. [原创]手把手教你Linux下的多线程设计(一) --Linux下多线程编程详解 原 ...
- Linux下实现多线程的生产者消费者问题
Linux下实现多线程的生产者消费者问题 一.原理的理解 生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制.在同一个线程地址空间内执行的两个线程 ...
- Linux下不使用qt自带sleep,Linux下Qt多线程编程
该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 作者:武汉华嵌嵌入式培训中心 技术部 以下和大家分享Linux平台下Qt两种多线程编程的方式: 1.使用Linux平台下的线程函数.以下是给出的代码片段: ...
- linux 下的 多线程http 下载器
Linux下多线程下载工具-Axel Axel是命令行下的多线程下载工具,支持断点续传,速度通常情况下是Wget的几倍. 它的官方网站: http://wilmer.gaa.st/main.php/a ...
- linux下串口多线程通信 ,多串口收发数据错乱问题解决办法
最近在写AM335x平台的串口测试工具,最开始的时候写的第一版本,测试一直很ok,但是存在一些缺陷,于是就想改进一下,没想到后面在新的板子测试,竟然发现了以个很致命的问题,在旧系统旧内核测试一切正常, ...
- Linux下实现多线程异步管道
目录 架构 代码 相关阅读 "最近在做F-Stack相关内容,F-Stack协议栈单线程独占异步轮询网卡,所以要求异步.但是又有多线程需要利用F-Stack进行发包,并且发包ff_sen ...
- Linux下的多线程編程
Linux下的多線程編程 本文出自:http://www.china-pub.com 引言 線程(thread)技術早在60年代就被提出,但真正應用多線程到操作系統中去,是在80年代中期,solari ...
- linux 中多进程下载工具,[转载]Linux 下安装多线程下载工具 proz
学习Linux,就不停的要到网上下载各种各样的源码包或rpm包,只在图形界面下操作,如果网络不是很流畅(比如我的adsl)通常很慢,而且不稳定,有时候会出现下载包不完整的情况,所以建议找个下载工具装上 ...
最新文章
- pandas计算滑动窗口中的中位数实战(Rolling Median of a Pandas Column):计算单数据列滑动窗口中的中位数、计算多数据列滑动窗口中的中位数
- android 日历按周获取,Android日历获取当前周,前几周和下周
- Boost.Asio技术文档汇总
- android attrs获取_Android 常用侧滑栏实现
- 记录用NoteExpress下载文献全文成功
- .jks或者.keystore文件查看MD5、SHA-1和SHA-256
- 线性回归相关系数c语言,线性回归中的相关系数;
- 单片机控制的双路有源滤波器设计
- mysql启动黑屏_红警win10黑屏和不显示菜单栏问题 只有声音没有图像的解决
- Python获取图片保存对应的文件夹
- UTI ( Uniform Type Identifier )
- 计算机安全概述ppt,计算机信息安全概述.ppt
- Android app界面设计工具AppInventor初体验
- 还不到4折:赶紧来抢券啊!!!
- 如何去除图片背景颜色?怎样将背景色变透明?
- 正确理解和判断PR劫持的方法(站长必看)
- 游戏热更新(XLua)专题一(知识点)
- 万达VS银泰 谁是最后的赢家?
- 6.hadoop文件数据库系列讲解
- rockchip rk3368(px5)车载开发之路1,原生代码系统正常启动