侧边栏壁纸
博主头像
noerror

虚灵不寐,众理具而万事出。

  • 累计撰写 239 篇文章
  • 累计创建 9 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

pthread_create函数用法详解

noerror
2022-10-04 / 0 评论 / 0 点赞 / 213 阅读 / 1,988 字 / 正在检测是否收录...

pthread_create函数用法详解

pthread_create函数简介

  • 头文件包含
#include <pthread.h>
  • 函数定义
int pthread_create(pthread_t * thread , const pthread_attr_t * attr ,
                   void *(* start_routine ) (void *), void * arg );
  • 编译链接选项
-pthread

pthread_create函数常见使用错误

  • 链接错误
    undefined reference to `pthread_create'
    解决办法:添加链接选项
-pthread
  • 编译错误
    warning: implicit declaration of function ‘pthread_create’ [-Wimplicit-function-declaration]
    解决办法:包含头文件
#include <pthread.h>

pthread_create函数详细描述

pthread_create ()函数在调用进程中启动一个新线程。新线程通过调用start_routine ();开始执行,arg作为start_routine ()的唯一参数传递
新线程以下列方式之一终止:

  • 它调用pthread_exit (3),指定一个退出状态值,该值可用于调用pthread_join (3)的同一进程中的另一个线程
  • 它从start_routine ()返回,这相当于用return语句中提供的值调用pthread_exit (3)。
  • 它已被取消(请参见pthread_cancel (3))
  • 进程中的任何线程都调用exit (3),或者主线程执行从main ()返回的操作,这将导致进程中所有线程的终止。

attr参数指向一个pthread_attr_t结构,其内容在线程创建时用于确定新线程的属性;这个结构是使用pthread_attr_init (3)和相关函数初始化的。如果attr为NULL,则使用默认属性创建线程。
在返回之前,对pthread_create ()的成功调用会将新线程的ID存储在thread ;指向的缓冲区中。在随后对其他pthreads函数的调用中,该标识符用于引用该线程。
新线程继承创建线程的信号掩码的副本( pthread_sigmask (3))新线程的挂起信号集为空( sigpending (2))新线程不继承创建线程的备用信号栈( sigaltstack (2))
新线程继承调用线程的浮点环境( fenv (3))
新线程的CPU时间时钟的初始值为0(请参见pthread_getcpuclockid (3)) Linux-specific details)。新线程继承调用线程的能力集的副本(请参见capabilities (7))和CPU关联掩码(请参见sched_setaffinity (2))

pthread_create函数返回值

成功时,pthread_create ()返回0;出错时,它返回一个错误号,并且*thread的内容是未定义的。

pthread_create函数错误码

  • EAGAIN 资源不足,无法创建另一个线程。
  • EAGAIN 遇到了系统对线程数的限制。有许多限制可能会触发此错误:达到了RLIMIT_NPROC软资源限制(通过setrlimit (2))设置的,它限制了真实用户ID的进程和线程数量);达到了内核系统范围内对进程和线程数量的限制/proc/sys/kernel/threads-max (请参见proc (5));或PID的最大数量),达到了/proc/sys/kernel/pid_max (请参见proc (5))
  • EINVAL attr 中的无效设置
  • EPERM 没有权限设置attr 中指定的调度策略和参数

pthread_create函数其他说明

有关pthread_create ()在*thread中返回的线程ID的更多信息,请参见pthread_self (3),除非使用了实时调度策略,否则在调用pthread_create ()之后,不确定哪个线程(emthe caller或the new thread(emwill next execute)。
如果一个线程是可接合的,那么另一个线程可以调用pthread_join (3)等待线程终止并获取其退出状态,线程可以是joinable或detached 。只有当终止的可接合线程被接合时,它的最后一个资源才会释放回系统。当一个分离的线程终止时,它的资源会自动释放回系统:不可能为了获得它的退出状态而加入该线程。使线程分离对于应用程序不需要关心其退出状态的某些类型的守护进程线程很有用。默认情况下,新线程是在可接合状态下创建的,除非attr被设置为在分离状态下创建线程(使用pthread_attr_setdetachstate (3))
在NPTL线程实现中,如果RLIMIT_STACK软资源限制"at the time the program started"具有“无限”以外的任何值,那么它将确定新线程的默认堆栈大小。使用pthread_attr_setstacksize (3),可以在用于创建线程的attr参数中显式设置stack size属性,以获得默认值以外的堆栈大小。如果RLIMIT_STACK资源限制设置为“无限”,则每个体系结构的值用于堆栈大小。以下是一些体系结构的值:.rs.ts Allbox;lb lb l r。体系结构默认堆栈大小i3862 MB IA-6432 MB PowerPC4 MB S/3902 MB Sparc-322 MB Sparc-644 MB x86_642 MB

pthread_create函数使用举例

下面的程序演示了pthread_create ()的使用,以及pthreads API中的许多其他函数。
在下面的运行中,在提供NPTL线程实现的系统上,堆栈大小默认为“堆栈大小”资源限制所给出的值:

" ulimit \-s"
8192            # The stack size limit is 8 MB (0x800000 bytes)
" ./a.out hola salut servus"
Thread 1: top of stack near 0xb7dd03b8; argv_string=hola
Thread 2: top of stack near 0xb75cf3b8; argv_string=salut
Thread 3: top of stack near 0xb6dce3b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS

在下一次运行中,程序显式地将堆栈大小设置为1\MB(对创建的线程使用pthread_attr_setstacksize (3)):

" ./a.out \-s 0x100000 hola salut servus"
Thread 1: top of stack near 0xb7d723b8; argv_string=hola
Thread 2: top of stack near 0xb7c713b8; argv_string=salut
Thread 3: top of stack near 0xb7b703b8; argv_string=servus
Joined with thread 1; returned value was HOLA
Joined with thread 2; returned value was SALUT
Joined with thread 3; returned value was SERVUS

Program source&

#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>

#define handle_error_en(en, msg) \e
       do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

#define handle_error(msg) \e
       do { perror(msg); exit(EXIT_FAILURE); } while (0)

struct thread_info {    /* Used as argument to thread_start() */
   pthread_t thread_id;        /* ID returned by pthread_create() */
   int       thread_num;       /* Application\-defined thread # */
   char     *argv_string;      /* From command\-line argument */
};

/* Thread start function: display address near top of our stack,
  and return upper\-cased copy of argv_string */

static void *
thread_start(void *arg)
{
   struct thread_info *tinfo = arg;
   char *uargv;

   printf("Thread %d: top of stack near %p; argv_string=%s\en",
           tinfo\->thread_num, &p, tinfo\->argv_string);

   uargv = strdup(tinfo\->argv_string);
   if (uargv == NULL)
       handle_error("strdup");

   for (char *p = uargv; *p != \(aq\e0\(aq; p++)
       *p = toupper(*p);

   return uargv;
}

int
main(int argc, char *argv[])
{
   int s, opt, num_threads;
   pthread_attr_t attr;
   size_t 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 \(aqs\(aq:
           stack_size = strtoul(optarg, NULL, 0);
           break;

       default:
           fprintf(stderr, "Usage: %s [\-s stack-size] arg...\en",
                   argv[0]);
           exit(EXIT_FAILURE);
       }
   }

   num_threads = argc \- optind;

   /* Initialize thread creation attributes */

   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");
   }

   /* Allocate memory for pthread_create() arguments */

   struct thread_info *tinfo = calloc(num_threads, sizeof(*tinfo));
   if (tinfo == NULL)
       handle_error("calloc");

   /* Create one thread for each command\-line argument */

   for (int tnum = 0; tnum < num_threads; tnum++) {
       tinfo[tnum].thread_num = tnum + 1;
       tinfo[tnum].argv_string = argv[optind + tnum];

       /* The pthread_create() call stores the thread ID into
          corresponding element of tinfo[] */

       s = pthread_create(&tinfo[tnum].thread_id, &attr,
                          &thread_start, &tinfo[tnum]);
       if (s != 0)
           handle_error_en(s, "pthread_create");
   }

   /* Destroy the thread attributes object, since it is no
      longer needed */

   s = pthread_attr_destroy(&attr);
   if (s != 0)
       handle_error_en(s, "pthread_attr_destroy");

   /* Now join with each thread, and display its returned value */

   for (int 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\en",
               tinfo[tnum].thread_num, (char *) res);
       free(res);      /* Free memory allocated by thread */
   }

   free(tinfo);
   exit(EXIT_SUCCESS);
}
0

评论区