1、线程概述
与进程类似,线程(thread)是允许应用程序并发执行多个任务的一种机制。一个进程可以包含多个线程。同一个程序中的所有线程均会独立执行相同程序,且共享一份全局内存区域,其中包括初始化数据段、未初始化数据段,以及堆内存段。(传统意义上的UNIX进程只是多线程程序的一个特例,该进程只包含一个线程)
进程是CPU分配资源的最小单位,线程是操作系统调度执行的最小单位。
线程是轻量级的进程(LWP:Light Weight Process),在Linux环境下线程的本质是进程。
查看指定进程的LWP号:ps -Lf pid
2、线程和进程的区别
进程间的信息难以共享。由于除去只读代码段外,父子进程并未共享内存,因此必须采用一些进程通信方式,在进程间进行信息交换。
调用fork来创建进程的代价相对较高,即便利用写时复制技术,仍然需要复制诸如内存页表和文件描述符之类的多种进程属性,这意味着fork调用在时间上的开销依然不菲。
线程之间能够更方便、快速地共享信息。只需要将数据复制到共享(全局或堆)变量中即可。
创建线程比创建进程通常要快10倍甚至更多。线程间是共享虚拟地址空间的,无需采用写时复制来复制内存,也无需复制页表。
3、线程之间共享和非共享资源
共享资源:
进程ID和父进程ID;进程组ID和会话ID;用户ID和用户组ID;文件描述符表;文件系统的相关信息:文件权限掩码(umask)、当前工作目录;虚拟地址空间(除栈、text)
非共享资源:
线程ID;信号掩码;线程特有数据;error变量;实时调度策略和优先级;栈、本地变量和函数的调用链接信息
4、创建线程
/*
一般情况下,main函数所在的线程称之为主线程(main线程),其余创建的线程称之为子线程。
程序中默认只有一个进程,fork函数调用,2个进程。
程序中默认只有一个线程,pthread_create函数调用,2个线程。
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
- 功能:创建一个子线程
- 参数:
- thread:传出参数,线程创建成功后,子线程的线程ID被写到该变量中。
- attr:设置线程的属性,一般使用默认值NULL。
- start_routine:函数指针,这个函数是子线程需要处理的逻辑代码。
- arg:给第三个参数使用,传参。
- 返回值:
成功:0
失败:返回错误号。这个错误号和之前的errno不一样。
获取错误号的信息:char * strerror(int errnum)
*/
#include <stdio.h>
#include <pthread.h>
#include <string.h>