zoukankan      html  css  js  c++  java
  • 【Linux 编程】线程编程

      一个进程中可以包含多个线程。线程中包含了表示进程执行环境必须的信息,其中包括进程中标识线程的线程ID、一组寄存器值、栈、调度 优先级和策略、信号屏蔽字、errno变量以及线程私有数据。进程的所有信息对该进程的所有线程都是共享的,包括可执行的程序文本、程序的全局内存和堆内存、栈以及文件描述符。

      需要注意的是,进程ID是全局唯一的,但是线程ID只有在它所属的进程环境中有效

      通过调用函数pthread_create来创建线程(更多内容:man 3 pthread_create):

    1 #include <pthread.h>
    2 
    3 int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
    4 
    5 // Compile and link with -pthread
    View Code

      其中,参数arg作为线程开始函数start_routine的传递参数。若传递参数不止一个,则将这些参数放在一个结构体中,然后把这个结构的地址作为arg参数传入。

      注意,线程创建时并不能保证哪个线程会先运行:是新创建的线程还是调用线程

      若进程中任一线程调用exit,_Exit或_exit,那么整个进程会终止在不终止整个进程的情况下停止它的控制流单个线程可以通过以下三种方式退出

    1. 线程从start_routine中返回,则返回值就是线程的退出码;
    2. 线程可以被同一进程中的其他线程利用函数pthread_cancel函数来取消;
    3. 线程在start_routine中调用pthread_exit。

      同一进程中的其他线程可以通过函数pthread_join来获取指定线程的退出码(man 3 pthread_join)。若该函数第二个参数设置为NULL,则pthread_join函数将等待指定线程终止。在默认情况下,线程的之中状态会保存到对该线程调用pthread_join,如果线程已经处于分离状态,线程的底层存储资源可以在线程终止时立即被收回。当线程被分离时,并不能用pthread_join函数等待它的终止状态。

      同一进程中的其他线程可以调用函数pthread_cancel来请求取消同一进程中的其他线程。

      函数pthread_detach可以用于使线程进入分离状态。

      例子(来自pthread_create的linux说明文档):

      1 #include <pthread.h>
      2 #include <string.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <unistd.h>
      6 #include <errno.h>
      7 #include <ctype.h>
      8 
      9 #define handle_error_en(en, msg) \
     10                do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
     11 
     12 #define handle_error(msg) \
     13                do { perror(msg); exit(EXIT_FAILURE); } while (0)
     14 
     15 struct thread_info      /* Used as argument to thread_start() */
     16 {
     17     pthread_t thread_id;        /* ID returned by pthread_create() */
     18     int       thread_num;       /* Application-defined thread # */
     19     char     *argv_string;      /* From command-line argument */
     20 };
     21 
     22 /* Thread start function: display address near top of our stack,
     23    and return upper-cased copy of argv_string */
     24 
     25 static void *
     26 thread_start(void *arg)
     27 {
     28     struct thread_info *tinfo = (struct thread_info *) arg;
     29     char *uargv, *p;
     30 
     31     printf("Thread %d: top of stack near %p; argv_string=%s\n",
     32            tinfo->thread_num, &p, tinfo->argv_string);
     33 
     34     uargv = strdup(tinfo->argv_string);
     35     if (uargv == NULL)
     36         handle_error("strdup");
     37 
     38     for (p = uargv; *p != '\0'; p++)
     39         *p = toupper(*p);
     40 
     41     return uargv;
     42 }
     43 
     44 int
     45 main(int argc, char *argv[])
     46 {
     47     int s, tnum, opt, num_threads;
     48     struct thread_info *tinfo;
     49     pthread_attr_t attr;
     50     int stack_size;
     51     void *res;
     52 
     53     /* The "-s" option specifies a stack size for our threads */
     54 
     55     stack_size = -1;
     56     while ((opt = getopt(argc, argv, "s:")) != -1)
     57     {
     58         switch (opt)
     59         {
     60         case 's':
     61             stack_size = strtoul(optarg, NULL, 0);
     62             break;
     63 
     64         default:
     65             fprintf(stderr, "Usage: %s [-s stack-size] arg...\n",
     66                     argv[0]);
     67             exit(EXIT_FAILURE);
     68         }
     69     }
     70 
     71     num_threads = argc - optind;
     72 
     73     /* Initialize thread creation attributes */
     74 
     75     s = pthread_attr_init(&attr);
     76     if (s != 0)
     77         handle_error_en(s, "pthread_attr_init");
     78 
     79     if (stack_size > 0)
     80     {
     81         s = pthread_attr_setstacksize(&attr, stack_size);
     82         if (s != 0)
     83             handle_error_en(s, "pthread_attr_setstacksize");
     84     }
     85 
     86     /* Allocate memory for pthread_create() arguments */
     87 
     88     tinfo = calloc(num_threads, sizeof(struct thread_info));
     89     if (tinfo == NULL)
     90         handle_error("calloc");
     91 
     92     /* Create one thread for each command-line argument */
     93 
     94     for (tnum = 0; tnum < num_threads; tnum++)
     95     {
     96         tinfo[tnum].thread_num = tnum + 1;
     97         tinfo[tnum].argv_string = argv[optind + tnum];
     98 
     99         /* The pthread_create() call stores the thread ID into
    100            corresponding element of tinfo[] */
    101 
    102         s = pthread_create(&tinfo[tnum].thread_id, &attr,
    103                            &thread_start, &tinfo[tnum]);
    104         if (s != 0)
    105             handle_error_en(s, "pthread_create");
    106     }
    107 
    108     /* Destroy the thread attributes object, since it is no
    109        longer needed */
    110 
    111     s = pthread_attr_destroy(&attr);
    112     if (s != 0)
    113         handle_error_en(s, "pthread_attr_destroy");
    114 
    115     /* Now join with each thread, and display its returned value */
    116 
    117     for (tnum = 0; tnum < num_threads; tnum++)
    118     {
    119         s = pthread_join(tinfo[tnum].thread_id, &res);
    120         if (s != 0)
    121             handle_error_en(s, "pthread_join");
    122 
    123         printf("Joined with thread %d; returned value was %s\n",
    124                tinfo[tnum].thread_num, (char *) res);
    125         free(res);      /* Free memory allocated by thread */
    126     }
    127 
    128     free(tinfo);
    129     exit(EXIT_SUCCESS);
    130 }
    View Code

      运行结果

      

  • 相关阅读:
    球自由降落问题
    三次握手、四次挥手
    basicjava
    socket编程
    scanner和BufferedReader
    parseInt和valueOf
    正则表达式
    ASCII码常用值
    最大公约和最小公倍数
    查询语句
  • 原文地址:https://www.cnblogs.com/life91/p/3116520.html
Copyright © 2011-2022 走看看