linux线程

来源:互联网 发布:工程网络计划紧前工作 编辑:程序博客网 时间:2024/06/03 21:06

一:线程的概念:
我们知道进程中自己独立的地址空间运行,进程间共享数据需要用mmap或者进程间通信机制,我们也知道线程其实就是进程的一个执行分支,同一个进程的多个线程它们公用着进程的地址空间。因此数据段,和全局变量都是共享的。除此之外各线程还共享一下进程资源和环境:
1:文件描叙符表file_struct;
2:每种信号的处理方式(SIG_IGN,SIG_DFL或者自定义的信号处理函数)
3:当前工作组目录
4:用户id和组id
当然线程有些资源是每个线程各有一份的:
1:线程id
2:上下文,包括各种寄存器的值,程序计数器和栈指针
3:栈空间
4:调度优先级
线程库函数是有POSIX标准定义的,称为POSIXthread或者thread,在linux中线程函数在libpthread共享库中,因此编译时要加上-lpthread
二:创建线程
创建线程要用pthread_creat函数:
这里写图片描述
1:返回值:成功返回0,失败返回值错误号,以前我们知道系统函数是成功返回0,失败返回-1;而错误号保存在全局变量errno中,而pthread库的函数都是通过返回值返回错误号,虽然每个线程也都有一个errno,但是这时为了兼容其他函数接口而提供的,pthread库本身并不使用它,通过返回值,返回错误码更加清晰
2:attr表示线程属性,线程调用pthread_ctreate时创建新线程,当前线程pthread_create()将继续往下执行,新线程的代码由start_routine()决定,start_routine()有一个参数,就是arg。
3: 错误信息:由于pthread_create的错误码不保存在errno中,因此不能直接⽤用perror(3)打印错误信息,可以先 用strerror(3)把错误码转换成错误信息再打印。
start_routine()的返回值类型也是void*。

//创建线程:#include<stdio.h>#include<pthread.h>#include<unistd.h>#include<sys/types.h>void*thread_run(void *arg){    printf("new  thread is  runuing:pid:%d,thread:%u\n",getpid(),pthread_self());    sleep(5);    return (void*)3;}int main(){pthread_t id;    pthread_create(&id,NULL,thread_run,NULL);    printf("main  thread is  runuing:pid:%d,thread:%u\n",getpid(),pthread_self());pthread_join(id,NULL);    return 0;}

这里写图片描述
三:终止线程:
如果需要终止某个线程而不是整个线程,有三种方法:
1:从线程函数return,这种方法对 主线程不能使用,从mian()函数return相当于调用exit
2:一个线程可以调用pthread_cancel终止同一进程中的另一个进程
3:线程可以通过调用那个pthread_exit终止自己
这里写图片描述
retval是void*类型,和线程函数返回值用法一样,其他线程调用pthread_join获得这个指针
注意:pthread_exit或者return返回的指针所指向的内存单元必须是全局的或者是malloc分配的,不能从线程函数的栈上分配。因为当其它线程得到这个返回值指针时,线程函数已经退出。
四:线程等待:
这里写图片描述
返回值:成功返回0,失败返回错误号
调用该函数的线程几个挂起等待,直到id的thread的线程终止。thread线程通过不同的方法终止,通过pthread_join得到的终止状态是不同的
1:如果thread线程通过return返回,value_ ptr所指向的单元里面存放着thread线程函数的返回值
2:如果thread线程被别的线程调用pthread_cancle异常终止,value_ptr所指向的单元里存放的是常数PTHREAD_CNACELED
3:如果thread线程是自己调用pthread_exit终止的,value_ptr所指向的单元存放的是传给pthread_exit的参数

//线程等待的实现![这里写图片描述](http://img.blog.csdn.net/20170605144936630?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZjIwMTY5MTM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)#include<stdio.h>#include<pthread.h>#include<unistd.h>#include<sys/types.h>void *thread1(void *val){    printf("thread1 is running\n");    return (void*)1;//返回值}void *thread2(void *val){    printf("thread2 is running\n");    pthread_exit((void*)2);//调用pthread_exit()终止当前线程}void *thread3(void* val){    printf("thread3 is running\n");  //  int i =0;    while(1)    {    printf("thread3 is running,wait for is cancle\n"); //调用pthread_cance被其他线程取消        sleep(1);    }    return NULL;}int main(){   pthread_t id;    void*ret;    //thread1 return   pthread_create(&id,NULL,thread1,NULL);    pthread_join(id,&ret);      printf("thread1 is  return:thread is:%u,code is:%d\n",pthread_self(),(int) ret);    //thread2_exit()   pthread_create(&id,NULL,thread2,NULL);    pthread_join(id,&ret);      printf("thread2 exit:thread is:%u,exit code is:%d\n",pthread_self(),(int) ret);    //thread3 cancle by other   pthread_create(&id,NULL,thread3,NULL);    sleep(2);    pthread_cancel(id);    pthread_join(id,&ret);      printf("thread3 cancle by other:thread is:%u,cancle code is:%d\n",pthread_self(),(int) ret);    return 0;}

这里写图片描述
可见在linux的pthread库中常数PTHREAD_CNACELED的值是-1;
一般情况下,线程终止后,其终止线程状态一直保留到其他线程调用pthread_join获取它的状态,但是线程也可以被置为detach状态,这样线程一旦被终止就立即回收它占有的资源,而不是保留与终止状态。
返回值:成功返回0,失败返回错误号
五:线程的合并和分离
在任意时间点上,线程是可结合的或者是可分离的(detached).一个线程可以被其他线程收回资源和杀死,在被其他线程回收之前,它的存储器资源是不释放,相反,一个分离的线程是不能被其他线程回收或者杀死,它的存储器资源是由系统自动释放。
1:默认情况下,线程被创建是可结合的,为了避免存储器泄露,每个可结合线程都应该要被显示可回收,要么通过那个pthread_join,要么通过pthread_detach函数被分离
如果一个线程结束运行没有被join,则他么的状态就是进程中的僵尸进程.
2:由于调用那个pthread_join,如果该进程没有运行结束,调用者会阻塞,如:在web服务器当中当主线程为每个新来的连续请求创建一个子线程进行处理的时候,主线程不希望因为pthread_join而阻塞,这时可在子线程加入
pthread_detach(pthead_self());
或者父线程调用
pthread_detach(pthead_id())(非阻塞,可立即返回)
3:将子线程状态设置为分离(detached),该线程运行结束会自动释放所有资源

#include<stdio.h>#include<pthread.h>#include<unistd.h>#include<sys/types.h>void*thread_run(void *arg){    printf("new  thread is  runuing:pid:%d,thread:%u\n",getpid(),pthread_self());    sleep(10);    return (void*)3;}int main(){   pthread_t id;    pthread_create(&id,NULL,thread_run,NULL);    printf("main  thread is  runuing:pid:%d,thread:%u\n",getpid(),pthread_self());pthread_detach(id);    sleep(5);  pthread_join(id,NULL);     return 0;}