线程函数
man pthreads了解线程相关内容。
线程函数成功返回0,失败返回错误码,不设置errno。POSIX.1-2001指出线程函数绝不会(never)返回EINTR(不会因EINTR而失败)。
- 线程创建
#include<pthead.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void * (*start_routine)(void *), void * restrict arg);
attr一般为NULL,采用系统默认属性。
int pthread_attr_init(pthread_attr_t *attr); int pthread_attr_destroy(pthread_attr_t *attr);
>>默认创建的线程是joinable的,可通过函数pthread_attr_setdetachstate()设置attr从而创建detached的线程。
>>可通过pthread_attr_setstacksize()设置attr从而创建指定栈大小的线程。pthread_attr_getstacksize()获取当线程栈大小。
成功返回0,失败返回错误号。
pthread_t无符号整型 typedef unsigned long int pthread_t
pthread库的函数都是通过返回值返回错误号,虽然每个线程都有一个errno,但并不使用它。因此不能调用perror打印错误信息,可先用strerror把返回值(错误码)转化为错误信息再打印。
注:线程函数参数和返回值都是void*,且函数返回的指针所指向的内存单元必须是全局的或者malloc分配的。
void * (*start_routine)(void *)
- 线程终止
终止线程有三种方法:
1)从线程函数return。
2)调用pthread_cancel()终止同一进程中的另一个线程。
3)线程可调用pthread_exit()终止自己。
void pthread_exit(void *value_ptr);
无返回值,总是成功。
注:pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者malloc分配的,不能在线程函数的栈上分配。
int pthread_cancel(pthread_t thread);
成功返回0,失败返回非零错误号。
被终止的线程的响应取决于可终止状态和类型(cancelability state and type).
注:如果任意一个线程调用exit或_exit,则整个进程的所有线程都终止。
- 获取终止状态
int pthread_join(pthread_t thread, void **retval);
等待线程终止,并获取线程退出状态。该线程必须是joinable。调用该函数的线程将挂起等待,直到id为thread的线程终止。阻塞函数
函数调用时注意参数:定义为void *res; 调用pthread_join(&res);最终调用参数(char *)res。
retval:
1)如果thread线程通过return返回,thread线程函数返回值。
2)pthread_cancel()异常终止,则retval所指向的单元存放常量PTHREAD_CANCELED(-1)。
3)自己调用pthread_exit()终止,retval存放pthread_exit参数。
- 分离线程
#include<pthread.h>
int pthread_detach(pthread_t thread);
标记线程thread为分离状态。当一个分离状态的线程终止时,它的资源自动释放给系统,不需要其他线程join。
成功返回0,失败返回错误号。
注:让线程自己pthread_detach(线程函数内调用)不好,库函数不是原子的。
注:不能对一个已经处于detach状态的线程调用pthread_join.==>EINVAL.
注:不能对同一线程调用两次pthread_join或pthread_detach,或者一个线程已经调用pthread_detach就不能再调用pthread_join了。
注:线程创建时,都应该调用pthread_join()或pthread_detach(),以使系统资源释放。
示例:pthread_detach(pthread_self());
- 获取线程id
pthread_t pthread_self(void);
函数总是成功,返回id。
- 信号函数
线程信号用pthread_sigmask, pthread_kill。
线程读写用pread/pwrite.(文件偏移不改变)
manpage示例
#include <ctype.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <pthread.h> #include <errno.h> #define handle_error_en(en, msg) do{ errno = en; perror(msg); exit(EXIT_FAILURE); } while(0) #define handle_error(msg) do { perror(msg); exit(EXIT_FAILURE); } while(0) struct thread_info{ pthread_t thread_id; int thread_num; char *argv_string; }; static void * t1(void *arg){ struct thread_info *tinfo = arg; char *uargv, *p; printf("Thread %d: top of stack near %p; argv_string=%s ", tinfo->thread_num, &p, tinfo->argv_string); uargv = strdup(tinfo->argv_string); if(uargv == NULL) printf("strdup error. "); for(p = uargv; *p != '