Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2381848
  • 博文数量: 298
  • 博客积分: 7876
  • 博客等级: 准将
  • 技术积分: 5500
  • 用 户 组: 普通用户
  • 注册时间: 2011-02-23 13:39
文章存档

2013年(2)

2012年(142)

2011年(154)

分类: LINUX

2011-04-04 16:32:08

初等线程相关

 

注意多线程编译时必须加上-lpthread选项,否则显示线程函数及其相关定义为未定义。

比如:

gcc filename.c -o filename -lpthread就行了 

#include

1.  int   pthread_equal(pthread_t tid1, pthread_t tid2)

       返回值:相等返回非0值, 不等返回0

2 pthread_t pthread_self(void)

       返回值:调用线程的线程ID

3 int pthread_create(pthread_t *restrict tidp,

const pthread_attr_t  *restrict attr,

void *(*start_rtn)(void), void *restrict arg);

       返回值:成功返回0 否则返回错误编号

restrict attr = NULL 取默认属性

线程简单属性相关:

4 int pthread_atrr_init(pthread_attr_t *attr)

5 int pthread_atrr_destroy(pthread_attr_t *attr)

       返回值:成功返回0 否则返回错误编号

 

线程简单属性表:(每中系统支持值请查《unix高级编程》中文版P314

detachstate  线程的分离状态

guardsize   线程栈末尾的警戒缓冲区的大小(字节)

stackaddr     线程栈的最低地址

stacksize       线程栈的大小(字节)

 

线程终止相关:

6 void pthread_exit(void *rval_ptr) rval_ptr参数是其返回值

7 int pthread_join(pthread_t thread, void **rval_ptr);

返回值:成功返回0 否则返回错误编号

8 int pthread_cancel(pthread_t tid)

       返回值:成功返回0,错误返回错误编号

9 void pthread_cleanup_push(void (*rtn)(void *), void *arg)

10void pthread_cleanup_pop(int execute)

       清理函数的顺序由pthread_cleanup_push函数注册顺序决定的,是逆序使用的,execute参数表示执行到pthread_cleanup_pop()时是否在弹出清理函数的同时执行该函数,为0表示不执行,非0为执行;这个参数并不影响异常终止时清理函数的执行。

11 int pthread_detach(pthread_t tid)

       返回值:成功返回0 否则返回错误编号

关于pthread_exitreturn

理论上说,pthread_exit()和线程宿体函数退出的功能是相同的,函数结束时会在内部自动调用pthread_exit()来清理线程相关的资源。但实际上二者由于编译器的处理有很大的不同。

在进程主函数(main())中调用pthread_exit(),只会使主函数所在的线程(可以说是进程的主线程)退出;而如果是return,编译器将使其调用进程退出的代码(如_exit()),从而导致进程及其所有线程结束运行。

其次,在线程宿主函数中主动调用return,如果return语句包含在pthread_cleanup_push()/pthread_cleanup_pop()对中,则不会引起清理函数的执行,反而会导致segment fault

 

例子程序1

#include

#include "apue.h"

#include

 

pthread_t ntid;

void

printids(const char *s)

{

    pid_t      pid;

    pthread_t  tid;

   

    pid = getpid();

    tid = pthread_self();

    printf("%s pid %u tid %u (0x%x)\n", s, (unsigned int) pid,

           (unsigned int)tid, (unsigned int)tid);

   

}

void *

thr_fn(void *arg)

{

    printids("new thread :");

    return ((void *)0);

//  pthread_exit((void*)0);

 

}

 

int

main(void)

{

    int err;

   

    err = pthread_create(&ntid, NULL, thr_fn, NULL);

    if(err != 0)

    {

       printf("can't create new thread : %s\n",

                   strerror(err));

       exit(-1);

    }

    printids("nain thread: ");

    sleep(1);

    return 0;

 

}

 

我电脑上运行结果:

new thread : pid 15265 tid 1082334400 (0x40831cc0)

nain thread:  pid 15265 tid 1073943168 (0x40031280)

 

例子程序2

 

#include "apue.h"

#include

 

struct foo{

    int a, b, c, d;

};

void

printfoo(const char *s,const struct foo *fp)

{

//  printf("%s\n", s);

    printf(s);

    printf(" struct at 0x%x\n", (unsigned int)fp);

    printf(" foo.a = %d \n", fp->a);

    printf(" foo.b = %d \n", fp->b);

    printf(" foo.c = %d \n", fp->c);

    printf(" foo.d = %d \n", fp->d);

}

 

void *

thr_fn1(void *arg)

{

    struct foo foo = {1, 2, 3, 4};

    printfoo("thread 1 :\n", &foo);

    pthread_exit((void *)&foo);

}

void *

thr_fn2(void *arg)

{

    printf("thread 2: ID is %d \n", pthread_self());

    return ((void *)0);

}

 

void

err_quit1(const char *s, const char *s1)

{

    printf("%s %s", s, s1);

    exit(-1);

}

int

main(void)

{

    int    err;

    pthread_t  tid1, tid2;

    struct foo *fp;

   

    err = pthread_create(&tid1, NULL, thr_fn1, NULL);

    if(err != 0)

    err_quit1("can't create new thread 1:", strerror(err));

    err = pthread_join(tid1, (void *)&fp);

    if(err != 0)

    err_quit1("join error :", strerror(err));

    sleep(1);

    printf("parent starting second thread \n");

    err = pthread_create(&tid2, NULL, thr_fn2, NULL);

    if(err != 0)

    err_quit1("can't create new thread 2:", strerror(err));

    sleep(1);

    printfoo("parent : \n", fp);

 

    return 0;

}

我电脑上运行结果:

thread 1 :

 struct at 0x4083189c

 foo.a = 1

 foo.b = 2

 foo.c = 3

 foo.d = 4

parent starting second thread

thread 2: ID is 1082334400

parent :

 struct at 0x4083189c

 foo.a = 1108543764

 foo.b = 0

 foo.c = 1082333364

 foo.d = 1108426211

 

注意:由于新建的线程是继承了主线程的堆栈,屏蔽字等信息的,所以在建立第二线程的时候可能已经把第一线程的数据给覆盖了,为了解决这一问题,可以采用全局变量和动态分配的方式。

 

例子程序3

*********************************************************************

#include

#include

#include

 

void

cleanup(void *arg)

{

        printf("cleanup: %s\n",(char *)arg);/*注意void *的用法*/

}

 

void *

thr_fn1(void *arg)        //退出时没有调用清理线程

{

        printf("thread 1 start\n");

        pthread_cleanup_push(cleanup,"thread 1 first handler");

        pthread_cleanup_push(cleanup,"thread 1 second handler");

        printf("thread 1 push complete\n");

        if(arg)

                return ((void * )1);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

        return ((void *)1);

 }

 

void *

thr_fn2(void *arg)                // Makes a call to pthread_exit

{

        printf("thread 2 start\n");

        pthread_cleanup_push(cleanup,"thread 2 first handler");

        pthread_cleanup_push(cleanup,"thread 2 second handler");

        printf("thread 2 push complete\n");

        if(arg)

                pthread_exit((void *)2);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

        pthread_exit((void *)2);

}

 

void *

thr_fn3(void *arg)   // Makes a call to pthread_cleanup_pop with a

//nonzero execute argument

{

        printf("thread 3 start\n");

        pthread_cleanup_push(cleanup,"thread 3 first handler");

        pthread_cleanup_push(cleanup,"thread 3 second handler");

        printf("thread 3 push complete\n");

        pthread_cleanup_pop(1);//0参数

        pthread_cleanup_pop(1);

        return 0;

}

void *

thr_fn4(void *arg)                // Responds to a cancellation request

{

        printf("thread 4 start\n");

        pthread_cleanup_push(cleanup,"thread 4 first handler");

        pthread_cleanup_push(cleanup,"thread 4 second handler");

        printf("thread 4 push complete\n");

        sleep(2);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

        return 0;

}

 

int main()

{

        int err;

        pthread_t tid1,tid2,tid3,tid4;

        void *tret;

 

        err=pthread_create(&tid1,NULL,thr_fn1,(void *)1);

        if(err!=0)

                printf("can't create thread 1:%s\n",strerror(err));

 

        err=pthread_create(&tid2,NULL,thr_fn2,(void *)1);

        if(err!=0)

                printf("can't create thread 2:%s\n",strerror(err));

 

        err=pthread_create(&tid3,NULL,thr_fn3,(void *)1);

        if(err!=0)

                printf("can't create thread 3:%s\n",strerror(err));

 

        err=pthread_create(&tid4,NULL,thr_fn4,(void *)1);

        if(err!=0)

                printf("can't create thread 4:%s\n",strerror(err));

 

        err=pthread_cancel(tid4);

        if(err!=0)

                printf("can't cancel with thread 4: %s\n",strerror(err));

        err=pthread_join(tid1,&tret);

        if(err!=0)

                printf("can't join with thread 1: %s\n",strerror(err));

        printf("thread 1 exit code %d\n",(int)tret);

 

        err=pthread_join(tid2,&tret);

        if(err!=0)

                printf("can't join with thread 2:%s\n",strerror(err));

        printf("thread 2 exit code %d\n",(int)tret);

 

        err=pthread_join(tid3,&tret);

        if(err!=0)

                printf("can't join with thread 3:%s\n",strerror(err));

        printf("thread 3 exit code %d\n",(int)tret);

 

        err=pthread_join(tid4,&tret);

        if(err!=0)

                printf("can't join with thread 4:%s\n",strerror(err));

        printf("thread 4 exit code %d\n",(int)tret);

 

        exit(0);

}

 

结果:

thread 1 start

thread 1 push complete

thread 2 start

thread 2 push complete

cleanup: thread 2 second handler

cleanup: thread 2 first handler

thread 3 start

thread 3 push complete

cleanup: thread 3 second handler

cleanup: thread 3 first handler

thread 4 start

thread 4 push complete

thread 1 exit code 1

thread 2 exit code 2

thread 3 exit code 0

cleanup: thread 4 second handler

cleanup: thread 4 first handler

thread 4 exit code -1

*********************************************************************

从输出结果可以看出,如果线程是从它的启动例程中返回而终止的话并且没有调用非0参数的pthread_cleanup_pop就不会调用其清理函数,还有注意的是我们企图取消线程4,后面调用pthread_join(tid4,&tret);出错,导致调用了清理函数。这一点对比与例子程序4

例子程序4

#include

#include

#include

 

void

cleanup(void *arg)

{

        printf("cleanup: %s\n",(char *)arg);/*注意void *的用法*/

}

 

void *

thr_fn1(void *arg)        //退出时没有调用清理线程

{

        printf("thread 1 start\n");

        pthread_cleanup_push(cleanup,"thread 1 first handler");

        pthread_cleanup_push(cleanup,"thread 1 second handler");

        printf("thread 1 push complete\n");

        if(arg)

                return ((void * )1);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

        return ((void *)1);

 }

 

void *

thr_fn2(void *arg)                // Makes a call to pthread_exit

{

        printf("thread 2 start\n");

        pthread_cleanup_push(cleanup,"thread 2 first handler");

        pthread_cleanup_push(cleanup,"thread 2 second handler");

        printf("thread 2 push complete\n");

        if(arg)

                pthread_exit((void *)2);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

        pthread_exit((void *)2);

}

 

void *

thr_fn3(void *arg)   // Makes a call to pthread_cleanup_pop with a

//nonzero execute argument

{

        printf("thread 3 start\n");

        pthread_cleanup_push(cleanup,"thread 3 first handler");

        pthread_cleanup_push(cleanup,"thread 3 second handler");

        printf("thread 3 push complete\n");

        pthread_cleanup_pop(1);//0参数

        pthread_cleanup_pop(1);

        return 0;

}

void *

thr_fn4(void *arg)                // Responds to a cancellation request

{

        printf("thread 4 start\n");

        pthread_cleanup_push(cleanup,"thread 4 first handler");

        pthread_cleanup_push(cleanup,"thread 4 second handler");

        printf("thread 4 push complete\n");

        sleep(2);

        pthread_cleanup_pop(0);

        pthread_cleanup_pop(0);

        return 0;

}

 

int main()

{

        int err;

        pthread_t tid1,tid2,tid3,tid4;

        void *tret;

 

        err=pthread_create(&tid1,NULL,thr_fn1,(void *)1);

        if(err!=0)

                printf("can't create thread 1:%s\n",strerror(err));

 

        err=pthread_create(&tid2,NULL,thr_fn2,(void *)1);

        if(err!=0)

                printf("can't create thread 2:%s\n",strerror(err));

 

        err=pthread_create(&tid3,NULL,thr_fn3,(void *)1);

        if(err!=0)

                printf("can't create thread 3:%s\n",strerror(err));

 

        err=pthread_create(&tid4,NULL,thr_fn4,(void *)1);

        if(err!=0)

                printf("can't create thread 4:%s\n",strerror(err));

 

/*        err=pthread_cancel(tid4);

        if(err!=0)

                printf("can't cancel with thread 4: %s\n",strerror(err));

  */      err=pthread_join(tid1,&tret);

        if(err!=0)

                printf("can't join with thread 1: %s\n",strerror(err));

        printf("thread 1 exit code %d\n",(int)tret);

 

        err=pthread_join(tid2,&tret);

        if(err!=0)

                printf("can't join with thread 2:%s\n",strerror(err));

        printf("thread 2 exit code %d\n",(int)tret);

 

        err=pthread_join(tid3,&tret);

        if(err!=0)

                printf("can't join with thread 3:%s\n",strerror(err));

        printf("thread 3 exit code %d\n",(int)tret);

 

        err=pthread_join(tid4,&tret);

        if(err!=0)

                printf("can't join with thread 4:%s\n",strerror(err));

        printf("thread 4 exit code %d\n",(int)tret);

 

        exit(0);

}

 

结果:

thread 1 start

thread 1 push complete

thread 2 start

thread 2 push complete

cleanup: thread 2 second handler

cleanup: thread 2 first handler

thread 3 start

thread 3 push complete

cleanup: thread 3 second handler

cleanup: thread 3 first handler

thread 4 start

thread 4 push complete

thread 1 exit code 1

thread 2 exit code 2

thread 3 exit code 0

thread 4 exit code 0

 

例子程序5

注意参数void*void **的用法

#include "apue.h"

#include

 

void

cleanup(void *arg)

{

printf((char *)arg);

printf("cleanup : %s\n", (char *)arg);

 

}

void *

thr_fn1(void *arg)

{

//printf("thread 1 start :%d\n", (int)(*arg));/*为什么会有错?*/

printf("thread 1 start :%d\n", (int)arg);

printf("thread 1 start :%d\n", (int *)arg);

//printf("thread 1 start :%d\n", *(int *)arg);/*??*/

pthread_cleanup_push(cleanup, "thread 1 first handler");

pthread_cleanup_push(cleanup, "thread 1 second handler");

printf("thread 1 push complete\n");

if(arg)

//pthread_exit((void *)1);

return ((void *)1);

pthread_cleanup_pop(0);

 

pthread_cleanup_pop(0);

//pthread_exit((void *)1);

return ((void *)1);

}

 

void *

thr_fn2(void *arg)

{

printf("thread 2 start\n");

pthread_cleanup_push(cleanup, "thread 2 first handler");

 

pthread_cleanup_push(cleanup, "thread 2 second handler");

printf("thread 2 push complete\n");

if(arg)

pthread_exit((void *)2);

pthread_cleanup_pop(0);

 

pthread_cleanup_pop(0);

pthread_exit((void *)2);

}

int

main(void)

{

    int err;

    pthread_t tid1, tid2;

    void *tret;

    err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);

    err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);

    err = pthread_join(tid1, &tret);

    printf("thread 1 exit code %d\n", (int)tret);/*??*/

    err = pthread_join(tid2, &tret);

    printf("thread 2 exit code %d\n", (int)tret);

      

    //return 0;

    exit(0);

}

 

结果:

thread 1 start :1

thread 1 start :1

thread 1 push complete

thread 2 start

thread 2 push complete

thread 2 second handlercleanup : thread 2 second handler

thread 2 first handlercleanup : thread 2 first handler

thread 1 exit code 1

thread 2 exit code 2

 

 

 

 

 

 

 

 

 

 

阅读(1012) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~