传送门:Linux多线程编程实例解析 .
传统多任务操作系统中一个可以独立调度的任务(或称之为顺序执行流)是一个进程。每个程序加载到内存后只可以唯一地对应创建一个顺序执行流,即传统意义的进程。每个进程的全部系统资源是私有的,如虚拟地址空间,文件描述符和信号处理等等。使用多进程实现多任务应用时存在如下问题:
1)任务切换,即进程间上下文切换,系统开销比较大。(虚拟地址空间以及task_struct 都需要切换)
2)多任务之间的协作比较麻烦,涉及进程间通讯。(因为不同的进程工作在不同的地址空间)
所以,为了提高系统的性能,许多操作系统规范里引入了轻量级进程的概念,也被称为线程。
一、线程基础
通常线程指的是共享相同地址空间的多个任务。线程最大的特点就是在同一个进程中创建的线程共享该进程的地址空间;但一个线程仍用task_struct 来描述,线程和进程都参与统一的调度。所以,多线程的好处便体现出来:
1)大大提高了任务切换的效率;因为各线程共享进程的地址空间,任务切换时只要切换task_struct 即可;
2)线程间通信比较方便;因为在同一块地址空间,数据共享;
当然,共享地址空间也会成为线程的缺点,因为共享地址空间,如果其中一个线程出现错误(比如段错误),整个线程组都会崩掉!
Linux之所以称呼其线程为LWP( Light Weight Process ),因为从内核实现的角度来说,它并没有为线程单独创建一个结构,而是继承了很多进程的设计:
1)继承了进程的结构体定义task_struct ;
2)没有专门定义线程ID,复用了PID;
3)更没有为线程定义特别的调度算法,而是沿用了原来对task_struct 的调度算法。
在最新的Linux内核里线程已经替代原来的进程称为调度的实际最小单位。
原来的进程概念可以看成是多个线程的容器,称之为线程组;即一个进程就是所有相关的线程构成的一个线程组。传统的进程等价于单线程进程。
每个线程组都有自己的标识符 tgid (数据类型为 pid_t ),其值等于该进程(线程组)中的第一个线程(group_leader)的PID。
1、创建线程
pthread_create()函数描述如下:
所需头文件 | #include <pthread.h> |
函数原型 | int pthread_create(pthread_t *thread,const pthread_attr_t *attr, void *(* routine)(void *), void *arg) |
函数参数 | thread :创建的线程 attr :指定线程的属性,NULL表示使用缺省属性 routine :线程执行的函数 arg :传递给线程执行的函数的参数 |
函数返回值 | 成功: 0 出错: -1 |
1)这里routine 是回调函数(callback),其函数类型由内核来决定,这里我们将其地址传给内核;这个函数并不是线程创建了就会执行,而是只有当其被调度到cpu上时才会被执行;具体回调函数的讲解,移步Linux C 函数指针应用---回调函数 .;</