pthread_create(3) - wariua/manpages-ko GitHub Wiki
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()
ν¨μλ νΈμΆ νλ‘μΈμ€ λ΄μμ μ μ€λ λλ₯Ό μμνλ€. μ μ€λ λλ 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)).
μ μ€λ λλ νΈμΆ μ€λ λμ μλ₯ μ§ν©λ€(capabilities(7))κ³Ό CPU μΉνμ± λ§μ€ν¬(sched_setaffinity(2)) μ¬λ³Έμ λ¬Όλ €λ°λλ€.
μ±κ³΅ μ pthread_create()
λ 0μ λ°ννλ€. μ€λ₯ μ μ€λ₯ λ²νΈλ₯Ό λ°ννλ©° *thread
λ΄μ©μ κ·μ λμ΄ μμ§ μλ€.
EAGAIN
- μ€λ λλ₯Ό μλ‘ μμ±ν μμμ΄ μΆ©λΆνμ§ μλ€.
EAGAIN
- μμ€ν
μ΄ μ μ©νλ μ€λ λ κ°μ νκ³μ λΆλͺμ³€λ€. μ΄ μ€λ₯λ₯Ό μΌμΌν¬ μ μλ μ νλ€μ΄ μ¬λ¬ κ°μ§ μλ€. μ€μ μ¬μ©μ IDλ³ νλ‘μΈμ€ λ° μ€λ λ κ°μλ₯Ό μ ννλ (setrlimit(2)μ ν΅ν΄ μ€μ ν)
RLIMIT_NPROC
μ°μ± μμ μ νμ λλ¬νκ±°λ, 컀λμ μμ€ν μ 체 νλ‘μΈμ€ λ° μ€λ λ κ°μ μ νμΈ/proc/sys/kernel/threads-max
(proc(5) μ°Έκ³ )μ λλ¬νκ±°λ, PID μ΅λ κ°μμΈ/proc/sys/kernel/pid_max
(proc(5))μ λλ¬ν κ²μ΄λ€. EINVAL
-
attr
μ μ ν¨νμ§ μμ μ€μ . EPERM
-
attr
μ μ§μ ν μ€μΌμ€λ§ μ μ± κ³Ό λ§€κ°λ³μλ₯Ό μ€μ ν κΆνμ΄ μλ€.
μ΄ μ μμ μ¬μ©νλ μ©μ΄λ€μ λν μ€λͺ μ attributes(7)λ₯Ό 보λΌ.
μΈν°νμ΄μ€ | μμ± | κ° |
---|---|---|
pthread_create() |
μ€λ λ μμ μ± | MT-Safe |
POSIX.1-2001, POSIX.1-2008.
pthread_create()
μ΄ *thread
λ‘ λ°ννλ μ€λ λ IDμ λν μΆκ° λ΄μ©μ pthread_self(3)λ₯Ό 보λΌ. μ€μκ° μ€μΌμ€λ§ μ μ±
μ μ¬μ© μ€μ΄μ§ μλ€λ©΄ pthread_create()
νΈμΆ νμ μ΄λ μ€λ λ(νΈμΆμ λλ μ μ€λ λ)κ° λ€μμΌλ‘ μ€νλ μ§κ° λΆνμ€νλ€.
μ€λ λλ ν©λ₯ κ°λ₯μ΄κ±°λ λΆλ¦¬ μνμ΄λ€. μ€λ λκ° ν©λ₯ κ°λ₯μ΄λ©΄ λ€λ₯Έ μ€λ λμμ pthread_join(3)μ νΈμΆν΄ κ·Έ μ€λ λμ μ’
λ£λ₯Ό κΈ°λ€λ¦¬κ³ μ’
λ£ μνλ₯Ό κ°μ Έμ¬ μ μλ€. μ’
λ£ν ν©λ₯ κ°λ₯ μ€λ λκ° ν©λ₯λκ³ λμμΌ μ€λ λμ λ§μ§λ§ μμλ€μ΄ μμ€ν
μΌλ‘ ν΄μ λλ€. λΆλ¦¬ μνμΈ μ€λ λκ° μ’
λ£ν λλ κ·Έ μμμ΄ μλμΌλ‘ μμ€ν
μΌλ‘ ν΄μ λλ€. κ·Έλ¦¬κ³ μ’
λ£ μνλ₯Ό μ»κΈ° μν΄ κ·Έ μ€λ λμ ν©λ₯νλ κ²μ΄ λΆκ°λ₯νλ€. μμ©μμ κ·Έ μ’
λ£ μνμ μ κ²½μ°μ§ μλ μΌλΆ λ°λͺ¬ μ€λ λμμ μ€λ λλ₯Ό λΆλ¦¬μν€λ κ²μ΄ μ μ©νλ€. μ€λ λλ₯Ό λΆλ¦¬ μνλ‘ μμ±νλλ‘ (pthread_attr_setdetachstate(3)λ‘) attr
μ μ€μ νμ§ μμλ€λ©΄ κΈ°λ³Έμ μΌλ‘ μ μ€λ λλ ν©λ₯ κ°λ₯ μνλ‘ μμ±λλ€.
NPTL μ€λ λ© κ΅¬νμμ νλ‘κ·Έλ¨ μμ μμ μ μ°μ± μμ μ ν RLIMIT_STACK
μ΄ "무μ ν" μΈμ κ°μ κ°μ§κ³ μμΌλ©΄ κ·Έ κ°μ΄ μ μ€λ λμ κΈ°λ³Έ μ€ν ν¬κΈ°λ₯Ό κ²°μ νλ€. κΈ°λ³Έκ³Ό λ€λ₯Έ μ€ν ν¬κΈ°λ₯Ό μνλ€λ©΄ μ€λ λ μμ±μ μ°λ attr
μΈμμ pthread_attr_setstacksize(3)μΌλ‘ μ€ν ν¬κΈ° μμ±μ λͺ
μμ μΌλ‘ μ€μ ν μ μλ€. RLIMIT_STACK
μμ μ νμ΄ "무μ ν"μΌλ‘ μ€μ λΌ μμΌλ©΄ μ€ν ν¬κΈ°μ μν€ν
μ²λ³ κ°μ μ¬μ©νλ€. λ€μμ λͺλͺ μν€ν
μ²μ κ°μ΄λ€.
μν€ν μ² | κΈ°λ³Έ μ€ν ν¬κΈ° |
---|---|
i386 | 2 MB |
IA-64 | 32 MB |
PowerPC | 4 MB |
S/390 | 2 MB |
Sparc-32 | 2 MB |
Sparc-64 | 4 MB |
x86_64 | 2 MB |
ꡬμμ΄ λ LinuxThreads ꡬνμμλ νλ‘μΈμ€ λ΄μ κ° μ€λ λκ° μλ‘ λ€λ₯Έ νλ‘μΈμ€ IDλ₯Ό κ°μ§λ€. μ΄λ POSIX μ€λ λ λͺ μΈ μλ°μ΄λ©° λ€λ₯Έ μ¬λ¬ νμ€ λΉμ€μ μ¬νλ€μ μμ²μ΄λ€. pthreads(7) μ°Έκ³ .
μλ νλ‘κ·Έλ¨μ pthread_create()
λ° pthreads APIμ λ€λ₯Έ μ¬λ¬ ν¨μλ€μ μ¬μ© λ°©μμ λ³΄μ¬ μ€λ€.
NPTL μ€λ λ© κ΅¬νμ μ 곡νλ μμ€ν μμμ λ€μ μ€νμμ μ€ν ν¬κΈ° κΈ°λ³Έκ°μ "μ€ν ν¬κΈ°" μμ μ νμ κ°μ΄λ€.
$ ulimit -s
8192 # μ€ν ν¬κΈ° μ ν 8MB (0x800000λ°μ΄νΈ)
$ ./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
λ€μ μ€νμμλ νλ‘κ·Έλ¨μμ λͺ μμ μΌλ‘ μμ± μ€λ λμ μ€ν ν¬κΈ°λ₯Ό (pthread_attr_setstacksize(3)λ‘) 1MBλ‘ μ€μ νλ€.
$ ./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
#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) \
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 { /* thread_start() μΈμλ‘ μ¬μ© */
pthread_t thread_id; /* pthread_create()μ΄ λ°ννλ ID */
int thread_num; /* μμ©μμ μ μν μ€λ λ λ²νΈ */
char *argv_string; /* λͺ
λ Ήν μΈμμμ μ¨ κ° */
};
/* μ€λ λ μμ ν¨μ: μ€ν μλ¨ κ·Όμ²μ μ£Όμλ₯Ό νμνκ³
argv_stringμ λλ¬Έμλ‘ λ°κΎΌ μ¬λ³Έμ λ°ν */
static void *
thread_start(void *arg)
{
struct thread_info *tinfo = arg;
char *uargv, *p;
printf("Thread %d: top of stack near %p; argv_string=%s\n",
tinfo->thread_num, &p, tinfo->argv_string);
uargv = strdup(tinfo->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (p = uargv; *p != '\0'; 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;
/* "-s" μ΅μ
μ μ€λ λμ μ€ν ν¬κΈ°λ₯Ό λνλ */
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...\n",
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");
}
/* pthread_create() μΈμλ₯Ό μν λ©λͺ¨λ¦¬ ν λΉ */
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];
/* pthread_create() νΈμΆμ΄ tinfo[]μ ν΄λΉ νλͺ©μ
μ€λ λ IDλ₯Ό μ μ₯ν¨ */
s = pthread_create(&tinfo[tnum].thread_id, &attr,
&thread_start, &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\n",
tinfo[tnum].thread_num, (char *) res);
free(res); /* μ€λ λκ° ν λΉν λ©λͺ¨λ¦¬ ν΄μ */
}
free(tinfo);
exit(EXIT_SUCCESS);
}
getrlimit(2), pthread_attr_init(3), pthread_cancel(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_getattr_np(3), pthread_join(3), pthread_self(3), pthread_setattr_default_np(3), pthreads(7)
2018-04-30