两种实现 linuxThreads Native POSIX Threads Library (NPTL)
- fork本身开销大,即使采用写时拷贝技术
- 父子进程间的通信须经过IPC
催生了轻量级进程——线程 进程有层次关系;同一进程下的线程对等,然而进程可连接任意进程,线程只能连接它所知道的线程
线程间的数据共享机制使得各线程间需要各种同步机制
当进程间采用共享内存通信时,必然需要类似的同步
IPC主要用于进程间 同步机制主要用于线程间
- 线程优点 共享数据 创建轻便
- 线程缺点 线程安全问题 共用进程地址空间 信号处理
- 线程独有的信息 线程ID 寄存器集 栈 errno 信号掩码 优先级
- errno的线程级实现必须通过#include <errno.h> 而不是 extern int errno
- 线程共享的信息 进程指令 数据 打开的文件 信号处理程序 当前目录 用户ID与组ID
API 成功返回0 失败直接返回正值=errno 编译选项 cc -pthread == #define _REENTRANT && -lpthread
- exec 进程中的第一个线程即进程本身
- int pthread_create(pthread_t* tid, const pthread_attr_t * attr, void* (*func)(void*) , void* arg);
- int pthread_join(pthread_t tid, void** retval); retval 获取返回状态
- pthread_t pthread_self(void); gettid()对于内核线程id 不等同于pthread_t
- int pthread_detach(pthread_t tid); 线程结束后可不使用jion清理 exit不会影响其他线程
- void pthread_exit(void* status);可在线程执行流中任意位置结束线程 线程函数return 进程 exit/_exit 均可使线程退出
- void pthread_canel(); 线程退出返回值由pthread_join接收
- void pthread_kill();
- int pthread_equal(pthread_t t1, pthread_t t2);相同返回非零 pthread_t在linux中一定全局唯一 其他实现中可能仅在同一进程中唯一
- void pthread_cleanup_push(void (*routine)(void*), void* arg); 设置清理函数栈
- void pthread_cleanup_pop(int execute);
线程属性设置
- int pthread_attr_init(pthread_attr_t*);
- int pthread_attr_setdetachstate(pthread_attr_t*, PTHREAD_CREATE_DETACHED);
- pthread_setcancelstate(int state, int* oldstate);
PTHREAD_CANCEL_DISABLE pthread_canel无效直到PTHREAD_CANCEL_ENABLEPTHREAD_CANCEL_ENABLE 线程默认状态
- pthread_setcanceltype(int type,int* oldtype);
PTHREAD_CANCEL_ASYNCHRONOUS pthread_canel后立即结束线程异步取消可能造成程序的混乱(执行流中几乎任意时刻被打断) pthread_canel* 3个函数为异步取消安全函数PTHREAD_CANCEL_DEFERED 线程默认 到达取消点(大部分阻塞型函数)才结束线程
- pthread_testcanel() 对于不包含取消点的线程,可周期性调用此函数进入取消点
fork出的子进程将继承线程的取消属性exec执行的新程序将采用默认取消属性
- pthread_attr_setstacksize()设置线程栈大小
- pthread_attr_setstack()设置线程栈大小和属性
- sysconf(_SC_THREAD_STACK_MION)获取特定平台线程栈最小值
NPTL在调用main之前已确定线程栈大小,故需提前ulimit -s设置而不是在main函数中设置
信号与线程
信号作用于某线程,动作为stop或terminate,则整个进程终止