进程fork的两个问题:
1. fork过于昂贵,需要把父进程的内存映像拷贝到子进程
2. fork返回之后父子进程之间信息的传递需要进程间通信(IPC)机制,子进程向父进程返回信息较困难
线程可称为轻权进程。
同一进程内的不同线程共享相同的全局内存,除此之外还共享:
进程指令、大多数数据文件、打开的文件(描述字)、信号处理函数和信号处置、当前工作目录、用户id和组id
每个线程有各自的:
线程id、寄存器集合(包括程序计数器和栈指针)、栈(用于存放局部变量和返回地址)、errno、信号掩码、优先级
以下为Unix中POSIX线程,有时称为Pthread,的一些基本函数:
头文件: #include <pthread.h>
1. int pthread_creat(pthread_t *tid, const pthread_attr_t *attr, void *(* func) (void *), void *arg)
功能:创建线程(当一个程序由exec执行时,初始线程或者主线程即被创建)
返回值: 创建成功,返回0; 创建失败,返回正Exxx值(与套接字返回值区别)
参数:
pthread_t *tid: 线程id标识,数据类型为pthread_t(通常为unsigned int),若线程成功创建,其id通过tid指针返回;
const pthread_attr_t *attr: 创建线程是可通过初始化一个取代缺省设置的pthread_attr_t变量指定线程的一些属性,如:优先级、初始栈大小、是否应该称为一个守护进程等。通常情况下采取缺省设置,将attr参数定义为空指针;
void *(* func) (void *)及void *arg:指定进程要执行的函数及该函数的参数。进程通过调用该函数开始执行,通过显式的调用pthread_exit()或者隐式的让该函数返回值结束。
注意: func及arg的声明
func:指向的函数作为参数接受一个通用指针(void *),又作为返回值返回一个通用指针(void *)。即我们可以把一个指针传递给线程,又允许线程返回一个指针
arg:func函数唯一调用的参数,若需要给func函数传递多个参数,则需要打包成一个结构,然后把该结构的地址作为单个参数传递
2. int pthread_join(pthread_t tid, void **status)
功能:等待一个给定线程终止
返回值:成功0, 出错返回正Exxx值
参数:
pthread_t tid:要等待线程的tid
void **status:若status指针为空,来自所等待线程的返回值(一个指向某对象的指针)将存入status所指向的位置
3. pthread_t pthread_self(void)
功能:每个线程都有一个在所属进程内标识自身的ID,使用pthread_self获取自身线程ID
ps:对比线程及unix进程,pthread_self类似于getpid
4. int pthread_detach (pthread_t tid)
功能:将指定线程转变为脱离状态
返回值:成功返回0,失败返回正Exxx值
ps:一个线程或者是可汇合的(joinable,缺省值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留到另一个线程对它调用pthread_join。脱离线程却象守护进程:当它们终止的时,所有相关资源都被释放,我们不能等待它们终止。如果一个线程需要知道另一个线程什么时候终止,那就最好保持第二个线程的可汇合状态。
本函数通常由想让自己脱离的线程调用: pthread_detach (pthread_self())
5. void pthread_exit(void *status)
功能:终止一个线程
无返回值
ps:若本线程未曾脱离,其线程ID和退出状态将一直留存到调用进程内的某个其他线程对它调用pthread_join
指针status不能指向局部于调用线程的对象,因为线程终止时这样的对象也消失