zoukankan      html  css  js  c++  java
  • 线程函数

    线程函数

    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 != ''; p++)
            *p = toupper(*p);
        
        return uargv;
    }
    
    int main(int argc, char ** argv)
    {
        int s, tnum, opt, num_threads;
        struct thread_info *tinfo;
        pthread_attr_t attr;
        int stack_size;
        void *res;
    
        /* the "-s" option specifies a stack size for our threads */
    
        stack_size = -1;
        while((opt = getopt(argc, argv, "s:")) != -1){
            switch(opt){
                case 's':
                    stack_size = strtoul(optarg, NULL, 0);
                    break;
                default:
                    fprintf(stderr, "Usage: %s [-s stack-size] arg ...
    ",
                        argv[0]);
                    exit(EXIT_FAILURE);
            }
        }
    
        num_threads = argc - optind;
    
        s = pthread_attr_init(&attr);
        if(s != 0)
            handle_error_en(s, "pthread_attr_init");
    
        if(stack_size > 0){
            s = pthread_attr_setstacksize(&attr, stack_size);
            if(s != 0)
                handle_error_en(s, "pthread_attr_setstacksize");
        }
    
        tinfo = calloc(num_threads, sizeof(struct thread_info));
        if(tinfo == NULL)
            handle_error("calloc");
    
        for(tnum = 0; tnum < num_threads; tnum++){
            tinfo[tnum].thread_num = tnum +1;
            tinfo[tnum].argv_string = argv[optind + tnum];
    
            s = pthread_create(&tinfo[tnum].thread_id, &attr, &t1, &tinfo[tnum]);
            if(s != 0)
                handle_error_en(s, "pthread_create");
        }
    
        s = pthread_attr_destroy(&attr);
        if(s != 0)
            handle_error_en(s, "pthread_attr_destroy");
    
        for(tnum = 0; tnum < num_threads; tnum++){
            s = pthread_join(tinfo[tnum].thread_id, &res);
            if(s != 0)
                handle_error_en(s, "pthread_join");
    
            printf("Joined with thread %d; returned value was %s
    ",
                tinfo[tnum].thread_num, (char*)res);
            free(res);
        }
    
        free(tinfo);
        exit(EXIT_SUCCESS);
    }

    执行:

    yuxi@ubuntu:~/test/pthread$ ./a.out 
    yuxi@ubuntu:~/test/pthread$ ./a.out -s 0x100000 abc def CHA
    Thread 3: top of stack near 0x7f7be5184f20; argv_string=CHA
    Thread 2: top of stack near 0x7f7be5285f20; argv_string=def
    Thread 1: top of stack near 0x7f7be5a74f20; argv_string=abc
    Joined with thread 1; returned value was ABC
    Joined with thread 2; returned value was DEF
    Joined with thread 3; returned value was CHA

     

  • 相关阅读:
    4.定时器
    LSTM分类层的理解
    对机器学习中end-to-end learning(端到端学习)的理解
    对非极大值限制(NMS)的理解
    ROI pooling
    softmax的理解
    长尾理论(long tail )的理解
    对双线性插值的理解
    RPN的理解
    卷积神经网络(CNN)和Faster-RCNN的理解
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/5071549.html
Copyright © 2011-2022 走看看