linux多线程pthread系列函数详解

linux多线程pthread系列函数详解

(一)为什么要引入线程

线程技术早在60年代就被提出,但是在80年代才真正使用到操作系统中。传统UNIX也支持多线程概念,但在一个进程中只允许有一个线程,这样多线程就意味着多进程。现在多线程技术已经被很多操作系统支持,包含Windows/NT,当然也包含Linux。

我们知道新建立一个进程的代价是非常昂贵的,内核需要分配一个新的地址空间,建立众多的数据表来维护他的数据段/代码段等。但是在一个进程中的多个线程,使用相同的地址空间,共享大部分数据,新建立一个线程花费的时间要远远小于新建一个进程,而且,线程之间的切换速度也远远小于进程的切换速度。

另外一点是通信的快速,进程由于有独立的地址空间,进程的数据传递往往使用通信的方式。而线程共享同一个数据空间,多个线程之间只需要做好数据保护,就可以直接使用数据,避免拷贝。

线程优点总结以下几个方面:

1)提高程序响应速度。比如按键响应这种耗时的操作可以在一个新建立的线程中去做,这样就不会影响其他的程序执行。

2)改善程序结构,复杂的逻辑可以按照业务拆分出多个线程处理,程序会利于修改与整理。

3)更好的应用于SMP系统,一个进程的多个线程可以分配到不同CPU上面运行。

(二)Pthread

Linux下的多线程遵从POSIX线程接口,简称pthread,在pthread库中提供。

pthread_create():创建一个线程

pthread_exit():退出一个线程

pthread_jion():阻塞当前线程,直到另一个线程执行结束

pthread_attr_init():设置线程是否脱离属性

pthread_kill():给线程发送kill信号

同步函数:

pthread_mutex_lock():互斥加锁

pthread_mutex_unlock():互斥锁解锁

pthread_cond_init():初始化条件变量

pthread_cond_signal():发送信号唤醒进程

pthread_cond_wait():等待条件变量的特殊事件发生

(三)pthread互斥锁的实现原理

pthread_create线程的创建:

最初的进程包含程序/资源/执行三部分,程序就是代码,资源主要包含系统层面上的内存/IO/信号资源等,而执行就是指执行上下文,包含代码对CPU的使用。后来设计者逐渐修正了进程的概念,允许资源不被进程严格独占,允许某些进程共享一部分资源比如信号/文件/数据内存/甚至代码。这就逐渐发展出轻量进程的概念,Linux2.4就已经实现了轻量进程的概念,通过调用clone的系统调用,设置不同的参数来设置是普通进程还是轻量级进程。clone最终调用do_fork函数,不同的clone_flag使do_fork有不同的行为:

LinuxThread使用(CLONE_VM|CLONE_FS|CLONE_FILES|CLONESIGHAND)调用clone函数,表明创建的新进程为共享内存/共享文件系统访问计数/共享文件描述符表/共享信号处理方式的意思。

LinuxThreads就是实现基于核心轻量级进程的“一对一”线程模型,一个线程实体对应一个核心轻量级进程,而线程之间的管理在核外函数库中实现。“一对一”模型的好处是线程的调度由核心完成,而其他诸如线程取消/线程间同步等工作都是在核心外的线程库中做的,在LinuxThreads中,专门为每个进程构造了一个管理线程,负责处理线程相关的管理工作。

pthread_mutex_lock互斥锁原理:

pthread_mutex_lock属于sleepwaiting类型的锁。Linux上的mutex互斥锁都是futex类型的锁。

futex(fast usermode mutex)快速用户去互斥锁的检查,futex时候由用户空间的一个对齐的整形变量和附在其上的内核空间的等待队列构成。这种锁的思想是,当锁没有竞争时,对位于用户空间的futex的整形变量进程操作(汇编语言调用CPU提供的原子操作来增加或减少它),当锁有竞争时,则通过内核态调用,将竞争失败的进程放入等待队列,并唤醒竞争成功的进程到就绪队列来是吸纳

(四)pthread在项目中的使用

在处理数据流的项目中,DevCapture是抓取视频流的类,注册硬件产生的视频流,一个DevCapture就是继承一个线程,CRecord/CStreamSend等类将数据处理函数注册到DevCapture中,由DevCapture的线程执行体调用各个注册的处理函数。

整个项目的关键处理程序在一个进程中,不同通道的流和具体线程的分配我不确定对应的策略。

数据流的发送处理在DevCapture中,没有经过数据拷贝。

接收是通过系统的协议栈获取上来的数据,必然由独立的线程recv,进行数据拼接,并模拟出一个类似DevCapture的ICapture类。

原文地址:https://www.cnblogs.com/minihaohao/p/5188906.html