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

     

  • 相关阅读:
    131. Palindrome Partitioning
    130. Surrounded Regions
    129. Sum Root to Leaf Numbers
    128. Longest Consecutive Sequence
    125. Valid Palindrome
    124. Binary Tree Maximum Path Sum
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    120. Triangle
    119. Pascal's Triangle II
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/5071549.html
Copyright © 2011-2022 走看看