当一个进程需要一个实体来完成某件事时,它可以fork一个子进程,让子进程去处理。Unix上大多网络服务器也是这么做的,但是fork有一些缺点:
1 昂贵,fork需要把父进程内存映像复制到子进程,并在子进程中复制所有的描述符,尽管有写时复制技术,但仍然昂贵。
2 父子进程之间需要进程间通信IPC,从子进程返回信息给父进程比较费力。
线程又称轻权进程,线程创建比进程快10-100倍。同一进程中的线程共享相同的全局内存,伴随的问题是同步问题。
同一进程中的线程共享:
进程指令
大多数数据
打开的文件描述符
信号处理函数和信号处置
当前工作目录
用户id和组id
每个线程各有:
线程id
寄存去集合,包括程序计数器和栈指针
栈
errno
信号掩码
优先级
pthread_creat函数
#include<pthread.h>
int pthread_creat(pthread_t *tid, const pthread_attr_t* attr,void*(*func)(void*),void* arg);
成功返回0,出错返回正的Exxx值
参数分别是线程id、线程属性(优先级、初始栈大小、是否成为守护线程)、该线程执行的函数及其函数参数。出错情况例如:线程数量上超过某个系统限制而不能创建线程时,返回的错误指示是EAGAIN,注意phread_creat不设置errno。
pthread_join函数
#include<pthread.h>
int pthread_join(pthread_t *tid,void **status);
成功返回0,出错返回正值Exxx
pthread_join用来等待一个线程终止,相当于进程中的waitpid。
我们必须指定线程id,所以无法像waitpid那样指定-1来等待所有的线程。如果status非空,来自所等待的线程的返回值(一个指向某个对象的指针)将存入由status指向的位置。
pthread_self函数
#include<pthread.h>
pthread_t pthread_self(void);
返回线程的线程ID。
每个线程调用pthread_self返回线程id。类似于进程中的getpid();
pthread_detach函数
#include<pthread.h>
int pthread_detch(pthread_t tid);
成功返回0,出错返回正Exxx
一个线程是可汇合的,或者可分离的,当一个可汇合的线程终止时,它的线程和退出状态将留存到另一个线程对它调用pthread_join为止,脱离的线程像守护进程,当他们终止时,所有相关资源将被释放,我们不能等待它们终止。如果一个线程需要知道另一个线程什么时候终止,那最好保持第二个线程的可汇合状态。pthread_detch把一个线程转变为脱离状态。
pthread_exit函数
#include<pthread.h>
void pthread_exit(void *status);
不能返回到调用者,如果线程未曾脱离,它的线程id和退出状态将一直保留到调用进程内某个其他线程对它调用pthread_join为止。status不能指向局部与调用线程的对象,因为线程终止局部对象也消失。
线程终止的另外两个方法:
启动线程的函数返回。其返回值void*就是线程的终止状态。
进程的main函数返回或者任何线程调用了exit,整个进程就终止,包括其内的任何线程。