当一个程序以进程的形式在内存中执行的时候,每个进程的空间地址是私有的,因此在进程间的上下文切换是,系统消耗比较大,为了提高系统的性能,许多操作系统引入了轻量级的进程概念,被称为线程。
在一个进程中创建的线程地址空间是共享的,在Linux中同样用task_struct 来描述线程,线程和进程都统一参与调度。
1)一个进程中的多线程共享了以下资源:
可执行命令
静态数据
进程中打开的文件描述符
信号处理函数
当前工作目录
组ID
用户ID
2)每个线程私有的资源:
线程ID
PC和相关的寄存器
堆栈(局部变量,返回地址)
错误号
信号掩码额优先级
执行状态和属性
每个线程都有自己的标识符tgid数据类型为pid_t,其等价于线程中第一个线程的PID
在线程中没有父子进程的概率,main函数是系统默认创建的,此时在共享进程的数据时就要考虑到数据的改变问题,后面会有线程的同步和互斥来改变这种情况
在一个进程中只有所有的进程结束,进程才结束,还有就是线程组中的某个线程死亡,可能会影响其他线程甚至整个进程。
线程的调试格式:gcc thread_creat .c -lpthread (-D_REENTRANT)
多线程的编程一般有创建线程,删除线程,控制线程:
/*
* int ptreah_create (pthread_t *thread,const phtread_attr_t *attr,
* void *(*routine)(void*),void *arg)
* thread 表示创建的线程可以是thrad1,thread2...
* attr 一般线程的属性,这里一般用NULL缺省表示
* routine是线程的执行函数
* arg是线程执行的函数参数
*int pthrea_exit(void *value_ptr) //成功返回0失败返回-1
*int pthread_join(pthread_t thread,void **value_ptr)
* thread 表示要等待的线程
* value_ptr 表示返回pthread_exit的状态值的地址
*成功返回0失败返回-1
*
*/
#include
#include
#include
#include
#include
struct thread_arg { int arg1; int arg2; }; char message[30] = "AAAAAAAAAA"; void *t1_routine(void *arg) { printf("thread 1 is running, argument is:%s\n", (char *)arg); strcpy(message, "BBBBBBBBBB"); printf("thread 1 is exiting...\n"); return NULL; } void *t2_routine(void *arg) { struct thread_arg *parg = (struct thread_arg *)arg; printf("thread 2 is running, arg1 = %d, arg2 = %d\n", parg->arg1, parg->arg2); printf("thread 2 is exiting...\n"); return NULL; } int main(int argc, char *argv[]) { pthread_t thread_1, thread_2; int retval; printf("main thread is running ...\n"); retval = pthread_create(&thread_1, NULL, t1_routine, (void *)message); if ( retval != 0) { perror("pthread_create error"); exit(-1); } struct thread_arg arg; arg.arg1 = 100; arg.arg2 = 200; retval = pthread_create(&thread_2, NULL, t2_routine, (void *)&arg); if ( retval != 0) { perror("pthread_create error"); exit(1); } /* * let main thread fly a while to allow child threads * get chance to print out sth on tty. */ sleep(2); printf("global string is updated to:%s\n", message); printf("main thread is exiting...\n"); return 0; }
#include
#include
#include
#include
#include
void *t1_routine(void *arg) { printf("thread_1: is running!\n"); /* do sth ... */ printf("thread_1: is exiting by self!\n"); pthread_exit(NULL); /* nothing to notify join caller */ } void *t2_routine(void *arg) { printf("thread_2: is running!\n"); /* do sth ... */ printf("thread_2: is leaving!\n"); return NULL; /* euqals to return 0 or directly w/o return */ } void *t3_routine(void *arg) { printf("thread_3: is running!\n"); while(1) { sleep(1); /* waiting to be cancelled by others */ } /* may not reach here if cancelled */ printf("thread_3: is leaving!\n"); } int main(int argc, char *argv[]) { pthread_t tid1, tid2, tid3; void *retval; /* create thread 1 */ if (0 != pthread_create(&tid1, NULL, t1_routine, NULL)) { perror("main: pthread_create thread_1 failed "); return 1; } else { printf("main: pthread_create thread_1[%lu] succeed!\n", tid1); } /* create thread 2 */ if (0 != pthread_create(&tid2, NULL, t2_routine, NULL)) { perror("main: pthread_create thread_2 failed "); return 1; } else { printf("main: pthread_create thread_2[%lu] succeed!\n", tid2); } /* create thread 3 */ if (0 != pthread_create(&tid3, NULL, t3_routine, NULL)) { perror("main: pthread_create thread_3 failed "); return 1; } else { printf("main: pthread_create thread_3[%lu] succeed!\n", tid3); } /* wait and join thread 1 */ if (0 != pthread_join(tid1, NULL)) { /* joiner doesn't want exit status */ perror("main: pthread_join thread_1 failed"); } else { printf("main: pthread_join thread_1[%lu] succeed.\n", tid1); } /* wait and join thread 2 */ if (0 != pthread_join(tid2, NULL)) { /* joiner doesn't want exit status */ perror("main: pthread_join thread_2 failed"); } else { printf("main: pthread_join thread_2[%lu] succeed.\n", tid2); } /* cancel thread 3 * Note the return status of pthread_cancel() merely informs * whether the cancellation request was successfully queued. * Joining with the cancelled thread is the only way to know * that cancellation has actually completed. */ if(0 != pthread_cancel(tid3)) { perror("main: pthread_cancel thread_3 failed"); return 1; } printf("main: pthread_cancel thread_3[%lu] succeed.\n", tid3); if (0 != pthread_join(tid3, &retval)) { perror("main: pthread_join thread_3 failed"); } else { /* * Till now we know the thread 3 was terminated. * After a canceled thread has terminated, a join * with that thread using pthread_join(3) obtains * PTHREAD_CANCELED as the thread's exit status. */ if (PTHREAD_CANCELED == retval) printf("main: pthread_join thread_3[%lu] succeed, " "thread_3 was cancelled.\n", tid3); else printf("main: thread_3 wasn't canceled " "(shouldn't happen!)\n"); } return 0; }