|
ÇöÀçÀ§Ä¡ : ¹Ì´Ï»çÀÌÆ®> Thread> Beginning> PthreadApiReference
Docbook ¿ø¹®
Pthread API Reference| 고친 과정 |
|---|
| 고침 0.9 | 2004³â 6¿ù 30ÀÏ 12½Ã | | | pthread Ãë¼Ò°ü·Ã api Ãß°¡ | | 고침 0.8 | 2003³â 10¿ù 9ÀÏ 12½Ã | | | pthread ½Ã±×³Î °ü·Ã api Ãß°¡ |
ÀÌ ¹®¼´Â pthread ·¹ÆÛ·±½º ¹®¼ÀÌ´Ù. pthread ¿¡¼ Á¦°øÇÏ´Â
¸ðµç ÇÔ¼öÀÇ ·¹ÆÛ·±½º¸¦ Á¦°øÇϰí ÀÖÁö´Â ¾ÊÁö¸¸,
ÀÚÁÖ ¾²Àϸ¸ÇÑ ´ëºÎºÐÀÇ ÇÔ¼öµéÀº Á¤¸®µÇ¾î ÀÖÀ½À¸·Î
Âü°íÇÒ¸¸ÇÑ °¡Ä¡°¡ ÀÖÀ»°ÍÀÌ´Ù.
ÀÌ ¹®¼¿¡ ºüÁø ³»¿ëµéÀº °è¼Ó Ãß°¡ÇØ ³ª°¥ ¿¹Á¤ÀÌ´Ù.
ÁÖ·Î ¾²·¹µå »ý¼º°ú Á¾·á¿¡ °ü·ÃµÈ °¡Àå ±âº»ÀûÀÎ ÇÔ¼öµéÀÌ´Ù.
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine)(void *), void *arg);
|
¾²·¹µå »ý¼ºÀ» À§Çؼ »ç¿ëÇÑ´Ù. ù¹øÂ° ¾Æ±Ô¸ÕÆ®ÀÎ thread ´Â
¾²·¹µå°¡ ¼º°øÀûÀ¸·Î »ý¼ºµÇ¾úÀ»¶§ »ý¼ºµÈ ¾²·¹µå¸¦ ½Äº°Çϱâ À§Çؼ »ç¿ëµÇ´Â
¾²·¹µå ½Äº°ÀÚÀÌ´Ù. µÎ¹øÂ° ¾Æ±Ô¸ÕÆ®ÀÎ attr Àº ¾²·¹µå Ư¼ºÀ»
ÁöÁ¤Çϱâ À§Çؼ »ç¿ëÇϸç, ±âº» ¾²·¹µå Ư¼ºÀ» ÀÌ¿ëÇϰíÀÚ ÇÒ°æ¿ì¿¡ NULL À»
»ç¿ëÇÑ´Ù. 3¹øÂ° ¾Æ±Ô¸ÕÆ®ÀÎ start_routine´Â
ºÐ±â½ÃÄѼ ½ÇÇàÇÒ ¾²·¹µå ÇÔ¼öÀ̸ç, 4¹øÂ° ¾Æ±Ô¸Õ´ÂÀÎ arg´Â
¾²·¹µå ÇÔ¼öÀÇ ÀÎÀÚÀÌ´Ù.
¼º°øÀûÀ¸·Î »ý¼ºµÉ°æ¿ì 0À» ¸®ÅÏÇÑ´Ù.
¿¹Á¦ : pthread_create.cc
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
// ¾²·¹µå ÇÔ¼ö
void *t_function(void *data)
{
int id;
int i = 0;
id = *((int *)data);
while(1)
{
printf("%d : %d\n", id, i);
i++;
sleep(1);
}
}
int main()
{
pthread_t p_thread[2];
int thr_id;
int status;
int a = 1;
int b = 2;
// ¾²·¹µå »ý¼º ¾Æ±Ô¸ÕÆ®·Î 1 À» ³Ñ±ä´Ù.
thr_id = pthread_create(&p_thread[0], NULL, t_function, (void *)&a);
if (thr_id < 0)
{
perror("thread create error : ");
exit(0);
}
// ¾²·¹µå »ý¼º ¾Æ±Ô¸ÕÆ®·Î 2 ¸¦ ³Ñ±ä´Ù.
thr_id = pthread_create(&p_thread[1], NULL, t_function, (void *)&b);
if (thr_id < 0)
{
perror("thread create error : ");
exit(0);
}
// ¾²·¹µå Á¾·á¸¦ ±â´Ù¸°´Ù.
pthread_join(p_thread[0], (void **)&status);
pthread_join(p_thread[1], (void **)&status);
return 0;
}
|
½ÇÇàµÈ ¾²·¹µå¿¡ ´ëÇØ¼´Â pthread_join µîÀÇ ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼ ¾²·¹µå
Á¾·á¶§±îÁö ±â´Ù·ÁÁà¾ß ÇÑ´Ù. ptherad_join Àº ÀÏÁ¾ÀÇ fork ÀÇ wait ¿Í
ºñ½ÁÇÏ°Ô ÀÛµ¿Çϸç, ¾²·¹µåÀÚ¿øÀ» ÇØÁ¦ ½ÃÄÑÁØ´Ù.
#include <pthread.h>
int pthread_join(pthread_t th, void **thread_return);
|
ù¹øÂ° ¾Æ±Ô¸ÕÆ® th´Â ±â´Ù¸±(join)ÇÒ ¾²·¹µå
½Äº°ÀÚÀ̸ç, µÎ¹øÂ° ¾Æ±Ô¸ÕÆ® thread_returnÀº
¾²·¹µåÀÇ ¸®ÅÏ(return) °ªÀÌ´Ù. thread_return ÀÌ NULL ÀÌ ¾Æ´Ò°æ¿ì
ÇØ´Ù Æ÷ÀÎÅÍ·Î ¾²·¹µå ¸®ÅÏ °ªÀ» ¹Þ¾Æ¿Ã¼ö ÀÖ´Ù.
pthread_joinc.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
// ¾²·¹µå ÇÔ¼ö
// 1Ãʸ¦ ±â´Ù¸°ÈÄ ¾Æ±Ô¸ÕÆ®^2 À» ¸®ÅÏÇÑ´Ù.
void *t_function(void *data)
{
int num = *((int *)data);
printf("num %d\n", num);
sleep(1);
return (void *)(num*num);
}
int main()
{
pthread_t p_thread;
int thr_id;
int status;
int a = 100;
thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
if (thr_id < 0)
{
perror("thread create error : ");
exit(0);
}
// ¾²·¹µå ½Äº°ÀÚ p_thread °¡ Á¾·áµÇ±æ ±â´Ù·È´Ù°¡
// Á¾·á¸®ÅϰªÀ» °¡Á®¿Â´Ù.
pthread_join(p_thread, (void *)&status);
printf("thread join : %d\n", status);
return 0;
}
|
detach ´Â "¶¼¾î³»´Ù" ¶ó´Â ¶æÀ» °¡Áö¸ç main ¾²·¹µå¿¡¼
pthread_create ¸¦ ÀÌ¿ëÇØ »ý¼ºµÈ ¾²·¹µå¸¦ ºÐ¸®½ÃŲ´Ù.
ÀÌ ÇÔ¼ö´Â ½Äº°¹øÈ£ thÀÎ ¾²·¹µå¸¦ detach ½Ã۴µ¥,
detach µÇ¾úÀ»°æ¿ì ÇØ´ç(detach µÈ) ¾²·¹µå°¡ Á¾·áµÉ°æ¿ì pthread_joinc
À» È£ÃâÇÏÁö ¾Ê´õ¶óµµ Áï½Ã ¸ðµç ÀÚ¿øÀÌ ÇØÁ¦(free) µÈ´Ù.
¿©±â¿¡¼´Â pthread_create È£ÃâÈÄ detach ÇÏ´Â ¹æ¹ýÀ» ¼³¸íÇϰí Àִµ¥,
pthread_create È£Ãâ½Ã¿¡ ¾²·¹µå°¡ detach µÇµµ·Ï ÇÒ¼öµµ ÀÖ´Ù.
ÀÌ¿¡ ´ëÇÑ ³»¿ëÀº pthread_attr_setdetachstate
¸¦ ´Ù·ç¸é¼ ¼³¸íÇϵµ·Ï ÇϰڴÙ.
¿¹Á¦ : pthread_detach.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
// ¾²·¹µå ÇÔ¼ö
// 1Ãʸ¦ ±â´Ù¸°ÈÄ ¾Æ±Ô¸ÕÆ®^2 À» ¸®ÅÏÇÑ´Ù.
void *t_function(void *data)
{
char a[100000];
int num = *((int *)data);
printf("Thread Start\n");
sleep(5);
printf("Thread end\n");
}
int main()
{
pthread_t p_thread;
int thr_id;
int status;
int a = 100;
printf("Before Thread\n");
thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
if (thr_id < 0)
{
perror("thread create error : ");
exit(0);
}
// ½Äº°¹øÈ£ p_thread ¸¦ °¡Áö´Â ¾²·¹µå¸¦ detach
// ½ÃÄÑÁØ´Ù.
pthread_detach(p_thread);
pause();
return 0;
}
|
À§ÀÇ ½î¾² Äڵ忡¼ detach ½ÃÄ×À»¶§¿Í ±×·¸Áö ¾Ê¾ÒÀ»¶§ÀÇ
¸Þ¸ð¸® »óȲÀ» ºñ±³Çغ¸±â ¹Ù¶õ´Ù.
detatach ¸¦ ÇßÀ»°æ¿ì ÇÁ·Î¼¼½ºÀÇ ¸Þ¸ð¸® »ç¿ëÀ²°ú detache ¸¦ ÁÖ¼®
ó¸®ÇßÀ»°æ¿ìÀÇ ¸Þ¸ð¸® »ç¿ëÀ²ÀÇ º¯È¸¦ ¼·Î ºñ±³Çغ¸¸é µÇ´Âµ¥,
detach ¸¦ »ç¿ëÇÏÁö ¾Ê¾ÒÀ»°æ¿ì t_function ÀÌ Á¾·á°¡ µÇ´õ¶óµµ
ÀÚ¿øÀÌ ÇØÁ¦µÇÁö ¾ÊÀ½À» º¼¼ö ÀÖÀ»°ÍÀÌ´Ù.
Å×½ºÆ®´Â °£´ÜÇÑ ½ºÅ©¸³Æ®¸¦ ÀÌ¿ëÇϵµ·Ï ÇÑ´Ù.
[root@localhost test]# while [ 1 ]; do ps -aux | grep pthread | grep -v grep | grep -v vim; sleep 1; done
root 2668 0.0 0.1 1436 292 pts/8 S 18:37 0:00 ./pthread_detach
root 2668 0.0 0.1 1436 292 pts/8 S 18:37 0:00 ./pthread_detach
|
À§ÀÇ ps ³»¿ë¿¡¼ 5¹øÂ° ÇʵåÀÇ º¯È¸¦ È®ÀÎÇÏ¸é µÈ´Ù.
pthread_exit ´Â ÇöÀç ½ÇÇàÁßÀÎ ¾²·¹µå¸¦ Á¾·á½Ã۰íÀÚ ÇÒ¶§ »ç¿ëÇÑ´Ù.
¸¸¾à pthread_cleanup_push °¡ Á¤ÀǵǾî ÀÖ´Ù¸é,
pthread_exit °¡ È£ÃâµÉ°æ¿ì cleanup handler °¡ È£ÃâµÈ´Ù.
º¸Åë ÀÌ cleanup handler Àº ¸Þ¸ð¸®¸¦ Á¤¸®ÇÏ´Â µîÀÇ ÀÏÀ» ÇÏ°Ô µÈ´Ù.
¿¹Á¦ : pthread_exit.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
// ¾²·¹µå ÇÔ¼ö
// 1Ãʸ¦ ±â´Ù¸°ÈÄ ¾Æ±Ô¸ÕÆ®^2 À» ¸®ÅÏÇÑ´Ù.
void *t_function(void *data)
{
int num = *((int *)data);
int i = 0;
while(1)
{
if (i == 3)
pthread_exit(0);
printf("loop %d\n", i);
i++;
sleep(1);
}
}
int main()
{
pthread_t p_thread;
int thr_id;
int status;
int a = 100;
thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
if (thr_id < 0)
{
perror("thread create error : ");
exit(0);
}
pthread_join(p_thread, (void **)&status);
return 0;
}
|
void pthrad_cleanup_push(void (*routine) (void *), void *arg);
|
À̰ÍÀº cleanup handlers ¸¦ ÀνºÅçÇϱâ À§Çؼ
»ç¿ëµÈ´Ù. pthread_exit(3)
°¡ È£ÃâµÇ¾î¼ ¾²·¹µå°¡ Á¾·áµÉ¶§ pthread_cleanup_push ¿¡
ÀÇÇØ¼ ÀνºÅçµÈ ÇÔ¼ö°¡ È£ÃâµÈ´Ù.
routineÀÌ ¾²·¹µå°¡ Á¾·áµÉ¶§ È£ÃâµÇ´Â
ÇÔ¼öÀÌ´Ù. arg´Â ¾Æ±Ô¸ÕÆ®ÀÌ´Ù.
cleanup handlers ´Â ÁÖ·Î ÀÚ¿øÀ» µÇµ¹·ÁÁְųª, mutex Àá±ÝµîÀÇ
ÇØÁ¦¸¦ À§ÇÑ ¿ëµµ·Î »ç¿ëµÈ´Ù.
¸¸¾à mutex ¿µ¿ª¿¡¼ pthread_exit °¡ È£ÃâµÇ¾î ¹ö¸±°æ¿ì
´Ù¸¥¾²·¹µå¿¡¼ ¿µ¿øÈ÷ block µÉ¼ö Àֱ⠶§¹®ÀÌ´Ù. ¶ÇÇÑ
malloc À¸·Î ÇÒ´ç¹ÞÀº ¸Þ¸ð¸®, ¿¸° ÆÄÀÏÁöÁ¤ÀÚ¸¦ ´Ý±â À§Çؼµµ
»ç¿ëÇÑ´Ù.
¿¹Á¦ : pthread_cleanup.c
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
// ¾²·¹µå ÇÔ¼ö
// 1Ãʸ¦ ±â´Ù¸°ÈÄ ¾Æ±Ô¸ÕÆ®^2 À» ¸®ÅÏÇÑ´Ù.
//
char *mydata;
void cleanup(void *);
void *t_function(void *data)
{
int num = *((int *)data);
int i = 0;
int a = 1;
// cleanup handler ·Î cleanup ÇÔ¼ö¸¦
// ÁöÁ¤ÇÑ´Ù.
pthread_cleanup_push(cleanup, (void *)&a);
mydata = (char *)malloc(1000);
while(1)
{
if (i == 3)
{
// pthread_exit °¡ È£ÃâµÇ¸é¼
// cleanup À» È£ÃâÇÏ°Ô µÈ´Ù.
pthread_exit(0);
return 1;
}
printf("loop %d\n", i);
i++;
sleep(1);
}
pthread_cleanup_pop(0);
}
int main()
{
pthread_t p_thread;
int thr_id;
int status;
int a = 100;
thr_id = pthread_create(&p_thread, NULL, t_function, (void *)&a);
if (thr_id < 0)
{
perror("thread create error : ");
exit(0);
}
pthread_join(p_thread, (void **)&status);
printf("Join finish\n");
}
// cleanup handler
void cleanup(void *myarg)
{
printf("thread is clean up\n");
printf("resource free\n");
free(mydata);
}
|
pthread_cleanup_push ¿Í ÇÔ²² »ç¿ëµÇ¸ç,
install µÈ cleanup handler À» Á¦°ÅÇϱâ À§Çؼ »ç¿ëµÈ´Ù.
¸¸¾à execute °¡ 0 À̶ó¸é, pthread_cleanup_push ¿¡ ÀÇÇØ
ÀνºÅçµÈ cleanup handler ¸¦ (½ÇÇà½ÃŰÁö ¾Ê°í)»èÁ¦¸¸ ½ÃŲ´Ù.
0 ÀÌ ¾Æ´Ñ ¼ýÀÚ¶ó¸é cleanup handler À» ½ÇÇà½ÃŰ°í »èÁ¦ µÈ´Ù.
»ç¿ë¿¹Á¦´Â 2.5절À» Âü°íÇ϶ó.
±×¸®°í pthread_cleanup_push ¿Í pthread_cleanup_pop Àº
¹Ýµå½Ã °°Àº ÇÔ¼ö³»ÀÇ °°Àº ·¹º§ÀÇ ºí·°¿¡¼
ÇѽÖÀ¸·Î »ç¿ëÇØ¾ß ÇÑ´Ù.
pthread_self¸¦ È£ÃâÇÏ´Â ÇöÀç
¾²·¡µåÀÇ ¾²·¹µå½Äº°ÀÚ¸¦ µÇµ¹·ÁÁØ´Ù.
¿¹Á¦ : pthread_self.c
#include <pthread.h>
#include <stdio.h>
void *func(void *a)
{
pthread_t id;
id = pthread_self();
printf("->%d\n", id);
}
int main(int argc, char **argv)
{
pthread_t p_thread;
pthread_create(&p_thread, NULL, func, (void *)NULL);
printf("%d\n", p_thread);
pthread_create(&p_thread, NULL, func, (void *)NULL);
printf("%d\n", p_thread);
return 1;
}
|
¾²·¹µå µ¿±âÈ¿Í °ü·ÃµÈ ÇÔ¼öµéÀÌ´Ù.
int pthread_mutex_init(pthread_mutex_t * mutex,
const pthread_mutex_attr *attr);
|
mutex ´Â ¿©·¯°³ÀÇ ¾²·¹µå°¡ °øÀ¯ÇÏ´Â µ¥ÀÌŸ¸¦ º¸È£Çϱâ
À§Çؼ »ç¿ëµÇ´Â µµ±¸·Î½á, º¸È£ÇϰíÀÚ ÇÏ´Â µ¥ÀÌŸ¸¦
´Ù·ç´Â Äڵ念¿ªÀ» ´ÜÁö Çѹø¿¡ ÇϳªÀÇ ¾²·¹µå¸¸ ½ÇÇà°¡´É
Çϵµ·Ï ÇÏ´Â ¹æ¹ýÀ¸·Î °øÀ¯µÇ´Â µ¥ÀÌŸ¸¦ º¸È£ÇÑ´Ù.
ÀÌ·¯ÇÑ Äڵ念¿ª(ÇϳªÀÇ ¾²·¹µå¸¸ Á¡À¯°¡´ÉÇÑ)À» critical section
À̶ó°í Çϸç, mutex °ü·Ã API ¸¦ ÀÌ¿ëÇØ¼ °ü¸®ÇÒ¼ö ÀÖ´Ù.
pthread_mutex_init ´Â mutex °´Ã¼¸¦ ÃʱâÈ
½Ã۱â À§Çؼ »ç¿ëÇÑ´Ù. ù¹øÂ° ÀÎÀÚ·Î ÁÖ¾îÁö´Â mutex °´Ã¼
mutex¸¦ ÃʱâȽÃ۸ç, µÎ¹øÂ° ÀÎÀÚÀÎ
attr ¸¦ ÀÌ¿ëÇØ¼ mutex Ư¼ºÀ» º¯°æÇÒ¼ö
ÀÖ´Ù. ±âº» mutex Ư¼ºÀ» ÀÌ¿ëÇϱ⠿øÇÑ´Ù¸é NULL À» »ç¿ëÇÏ¸é µÈ´Ù.
mutex Ư¼º(Á¾·ù) ¿¡´Â "fast", "recurisev", "error checking" ÀÇ Á¾·ù°¡
ÀÖÀ¸¸ç, ±âº»À¸·Î "fast" °¡ »ç¿ëµÈ´Ù.
// ¹ÂÅØ½º °´Ã¼ ¼±¾ð
pthread_mutex_t mutex_lock;
...
void *t_function()
{
pthread_mutex_lock(&mutex_lock);
// critical section
pthread_mutex_unlock(&mutex_lock);
}
int main()
{
pthread_t p_thread;
int state;
// ¹ÂÅØ½º °´Ã¼ ÃʱâÈ, ±âº» Ư¼ºÀ¸·Î ÃʱâÈ ÇßÀ½
pthread_mutex_init(&mutex_lock, NULL);
pthread_create(&p_thread, NULL, t_function, (void *)&a);
...
pthread_joinc(&p_thread, (void **)&status);
}
|
ÀÎÀÚ·Î ÁÖ¾îÁø ¹ÂÅØ½º °´Ã¼ mutex ¸¦
Á¦°ÅÇϱâ À§Çؼ »ç¿ëµÈ´Ù. mutex ´Â
pthread_mutex_init()ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼ »ý¼ºµÈ ¹ÂÅØ½º °´Ã¼ÀÌ´Ù.
pthread_mutex_destory ¸¦ ÀÌ¿ëÇØ¼ Á¦´ë·Î mutex ¸¦ »èÁ¦ÇÏ·Á¸é
ÀÌ mutex ´Â ¹Ýµå½Ã unlock »óÅÂÀÌ¿©¾ß ÇÑ´Ù.
pthread_mutex_lock ´Â critcal section ¿¡ µé¾î°¡±â À§Çؼ mutex lock
À» ¿äûÇÑ´Ù. ¸¸¾à ÀÌ¹Ì ´Ù¸¥ ¾²·¹µå¿¡¼ mutex lock ¸¦ ¾ò¾î¼ »ç¿ëÇϰí
ÀÖ´Ù¸é ´Ù¸¥ ¾²·¹µå¿¡¼ mutex lock(¹ÂÅØ½º Àá±Ý) À»
ÇØÁ¦ÇÒ¶§±îÁö(»ç¿ëÇÒ¼ö ÀÖÀ»¶§±îÁö) ºí·° µÈ´Ù.
¸¸¾à ´Ù¸¥ ¾î¶² ¾²·¹µå¿¡¼µµ mutex lock À» »ç¿ëÇϰí ÀÖÁö ¾Ê´Ù¸é,
Áï½Ã mutex lock À» ¾òÀ»¼ö ÀÖ°Ô µÇ°í critcal section ¿¡ ÁøÀÔÇϰÔ
µÈ´Ù. critcal section ¿¡¼ÀÇ ¸ðµç ÀÛ¾÷À» ¸¶Ãļ
»ç¿ëÇϰí ÀÖ´Â mutex lock ÀÌ ´õÀÌ»ó ÇÊ¿ä ¾ø´Ù¸é pthread_mutex_unlock ¸¦
È£ÃâÇØ¼ mtuex lock ¸¦ µÇµ¹·ÁÁØ´Ù.
critical section ¿¡¼ÀÇ ¸ðµç ÀÛ¾÷À» ¸¶Ä¡°í mutex lock À» µ¹·ÁÁÖ±â
À§Çؼ »ç¿ëÇÑ´Ù. pthread_mutex_unlock ¸¦ ÀÌ¿ëÇØ¼ mutex lock ¸¦
µÇµ¹·ÁÁÖ¸é ´Ù¸¥ ¾²·¹µå¿¡¼ mutex lock ¸¦ ¾òÀ»¼ö ÀÖ´Â »óŰ¡ µÈ´Ù.
int pthread_cond_init(pthread_cond_t *cond,
const pthread_cond_attr *attr);
|
pthread_cond_init´Â Á¶°ßº¯¼ö
(condition variable) cond¸¦
ÃʱâÈÇϱâ À§Çؼ »ç¿ëÇÑ´Ù. attr ¸¦
ÀÌ¿ëÇØ¼ Á¶°Çº¯¼öÀÇ Æ¯¼ºÀ» º¯°æÇÒ¼ö ÀÖÀ¸¸ç, NULL À»
ÁÙ°æ¿ì ±âº»Æ¯¼ºÀ¸·Î ÃʱâȵȴÙ.
Á¶°Çº¯¼ö cond´Â »ó¼ö
PTHREAD_COND_INITIALIZER À» ÀÌ¿ëÇØ¼µµ
ÃʱâÈ ÇÒ¼ö ÀÖ´Ù. Áï ´ÙÀ½°ú °°Àº 2°¡Áö ÃʱâÈ ¹æ¹ýÀÌ
Á¸ÀçÇÑ´Ù.
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
or
pthread_cond_init(&cond, NULL);
|
Á¶°Çº¯¼ö cond¿¡ ½Ã±×³¯À» º¸³½´Ù.
½Ã±×³¯À» º¸³¾°æ¿ì cond¿¡¼ ±â´Ù¸®´Â(wait)
¾²·¹µå°¡ ÀÖ´Ù¸é ¾²·¹µå¸¦ ±ú¿ì°Ô µÈ´Ù(ºÀ¼â°¡ Ç®¸²).
¸¸¾à Á¶°Çº¯¼ö cond¸¦ ±â´Ù¸®´Â ¾²·¹µå°¡
¾ø´Ù¸é, ¾Æ¹«·± Àϵµ ÀϾÁö ¾Ê°ÔµÇ¸ç,
¿©·¯°³ÀÇ ¾²·¹µå°¡ ±â´Ù¸®°í ÀÖ´Ù¸é ±×Áß ÇϳªÀÇ ¾²·¹µå¿¡°Ô¸¸
Àü´ÞµÈ´Ù. À̶§ ¾î¶² ¾²·¹µå¿¡°Ô ½ÅÈ£°¡ Àü´ÞµÉÁö´Â ¾Ë¼ö ¾ø´Ù.
Á¶°Çº¯¼ö cond¿¡¼ ±â´Ù¸®´Â(wait) ¸ðµç
¾²·¹µå¿¡°Ô ½ÅÈ£¸¦ º¸³»¼, ±ú¿î´Ù´Â Á¡À» Á¦¿ÜÇϰí´Â
pthread_cond_signal°ú µ¿ÀÏÇÏ°Ô ÀÛµ¿ÇÑ´Ù.
Á¶°Çº¯¼ö cond¸¦ ÅëÇØ¼ ½ÅÈ£°¡ Àü´ÞµÉ¶§±îÁö
ºí·°µÈ´Ù. ¸¸¾à ½ÅÈ£°¡ Àü´ÞµÇÁö ¾Ê´Â´Ù¸é ¿µ¿øÈ÷ ºí·°µÉ¼öµµ ÀÖ´Ù.
pthread_cond_wait´Â ºí·°µÇ±â Àü¿¡
mutex Àá±ÝÀ» ÀÚµ¿À¸·Î µÇµ¹·ÁÁØ´Ù.
int pthread_cond_timedwait(pthread_cont_t *cond, pthread_mutex_t *mutex,
const struct timespec *abstime);
|
Á¶°Çº¯¼ö cond¸¦ ÅëÇØ¼ ½ÅÈ£°¡ Àü´ÞµÉ¶§±îÁö
ºí·°µÇ¸ç ÀÚµ¿À¸·Î mutexÀ» µ¹·ÁÁÖ´Â Á¡¿¡¼´Â
pthread_cond_wait¿Í µ¿ÀÏÇÏ´Ù.
±×·¯³ª ½Ã°£Ã¼Å©°¡ °¡´ÉÇØ¼ abstime½Ã°£µ¿¾È
½ÅÈ£°¡ µµÂøÇÏÁö ¾Ê´Â´Ù¸é error ¸¦ ¹ß»ýÇÏ¸é¼ ¸®ÅÏÇÑ´Ù.
À̶§ ¸®ÅϰªÀº ETIMEDOUT ÀÌ´Ù. errno °¡ ¼¼ÆÃµÇ´Â°Ô ¾Æ´Ñ, ¸®ÅϰªÀ¸·Î
¿¡·¯°¡ ³Ñ¾î¿À´Â°Í¿¡ ÁÖÀÇÇØ¾ß ÇÑ´Ù.
¶ÇÇÑ pthread_cond_timedwaitÇÔ¼ö´Â
´Ù¸¥ signal ¿¡ ÀÇÇØ¼ interrupted µÉ¼ö ÀÖÀ¸¸ç
À̶§ EINTR À» ¸®ÅÏÇÑ´Ù. ÀÌ ÇÔ¼ö¸¦ ¾µ¶§´Â interrupted »óȲ¿¡
´ëÇÑ Ã³¸®¸¦ ÇØÁÖ¾î¾ß ÇÑ´Ù.
pthread_cond_init¸¦ ÅëÇØ¼ »ý¼ºÇÑ
Á¶°Çº¯¼ö cond¿¡ ´ëÇÑ ÀÚ¿øÀ» ÇØÁ¦ÇÑ´Ù.
destroy ÇÔ¼ö¸¦ È£ÃâÇϱâ Àü¿¡
¾î¶² ¾²·¹µåµµ cond¿¡¼ÀÇ ½Ã±×³ÎÀ»
±â´Ù¸®Áö ¾Ê´Â°É È®ÀÎÇØ¾ß ÇÑ´Ù. ¸¸¾à
cond ½Ã±×³ÎÀ» ±â´Ù¸®´Â ¾²·¹µå°¡ Á¸ÀçÇÑ´Ù¸é
ÀÌ ÇÔ¼ö´Â ½ÇÆÐÇϰí EBUSY ¸¦ ¸®ÅÏÇÑ´Ù.
À̹øÀå¿¡¼ ¼³¸íÇÑ ¾²·¹µå µ¿±âÈ °ü·Ã ÇÔ¼öÀÇ ÀÌÇØ¸¦ µ½±â À§Çؼ
°£´ÜÇÑ ¿¹Á¦¸¦ ÁغñÇß´Ù. ¼³¸íÀº ÁÖ¼®À¸·Î ´ë½ÅÇÑ´Ù.
¿¹Á¦ : pthrad_sync_api.c
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
using namespace std;
void *ping(void *);
void *pong(void *);
pthread_mutex_t sync_mutex;
pthread_cond_t sync_cond;
pthread_mutex_t gmutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t gcond = PTHREAD_COND_INITIALIZER;
int main()
{
vector<void *(*)(void *)> thread_list;
vector<pthread_t> tident(10);
int thresult;
int status;
int i;
pthread_mutex_init(&sync_mutex, NULL);
pthread_cond_init(&sync_cond, NULL);
thread_list.push_back(pong);
thread_list.push_back(ping);
for(i = 0; i < thread_list.size(); i++ )
{
pthread_mutex_lock(&sync_mutex);
if (pthread_create(&tident[i], NULL, thread_list[i], (void *)NULL) <0)
{
perror("error:");
exit(0);
}
pthread_cond_wait(&sync_cond, &sync_mutex);
pthread_mutex_unlock(&sync_mutex);
}
for (i = 0; i < tident.size(); i++)
{
pthread_join(tident[i], (void **)&status);
}
}
void *ping(void *data)
{
int i=0;
pthread_mutex_lock(&sync_mutex);
pthread_cond_signal(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
while(1)
{
pthread_mutex_lock(&gmutex);
printf("%d : ping\n", i);
pthread_cond_signal(&gcond);
pthread_cond_wait(&gcond, &gmutex);
pthread_mutex_unlock(&gmutex);
usleep(random()%100);
i++;
}
}
void *pong(void *data)
{
int i = 0;
pthread_mutex_lock(&sync_mutex);
sleep(1);
pthread_cond_signal(&sync_cond);
pthread_mutex_unlock(&sync_mutex);
while(1)
{
pthread_mutex_lock(&gmutex);
pthread_cond_wait(&gcond, &gmutex);
printf("%d : pong\n", i);
pthread_cond_signal(&gcond);
pthread_mutex_unlock(&gmutex);
i++;
}
}
|
À§ÀÇ ¿¹Á¦´Â ping&pong ÇÁ·Î±×·¥À¸·Î ping ¾²·¹µå¿Í pong ¾²·¹µå°¡
°¢°¢ ¹ø°¥¾Æ°¡¸é¼ "ping", "pong" À» ³¯¸®´Â ÇÁ·Î±×·¥ÀÌ´Ù.
2°³ÀÇ ¿µ¿ª¿¡ °ÉÃļ Å©¸®Æ¼Äü½¼ÇÀÌ
ÁöÁ¤µÇ¾î ÀÖÀ¸¸ç °¢ Å©¸®Æ¼Äü½¼Ç¾È¿¡´Â ¾²·¹µå µ¿±âȸ¦ À§Çؼ
ptread_cond_signal ÀÌ ¾²¿©Áö°í ÀÖ´Ù.
À§ÀÇ ÄÚµå´Â ±âº»ÀûÀ¸·Î pong ¾²·¹µå°¡ ¸ÕÀú ½Ã±×³ÎÀ» ´ë±âÇϰí
ÀÖ´Ù°¡ ±× ÈÄ ping ¾²·¹µå°¡ ÁøÀÔÇØ¼ "ping"À» ³¯¸®°í ½Ã±×³ÎÀ»
¹ß»ý½Ã۸é "pong" ¸Þ½ÃÁö¸¦ ¹ß»ý½Ã۵µ·Ï µÇ¾î ÀÖ´Ù. ±×·¸´Ù¸é
while ¹®¿¡ ÀÖ´Â Å©¸®Æ¼Äà ¼½¼Ç¿¡ ¹Ýµå½Ã pong ¾²·¹µå°¡ ¸ÕÀú
ÁøÀÔÇÒ¼ö ÀÖµµ·Ï ¸¸µé¾îÁà¾ß ÇÒ°ÍÀÌ´Ù.
±×·¡¼ À§ÀÇ Äڵ忡¼´Â pong ¾²·¹µå¸¦ ¸ÕÀú »ý¼º½ÃÄ×´Ù.
±×·¯³ª À̰͸¸À¸·Î´Â ÃæºÐÇÏÁö ¾Ê´Ù. ¿¹¸¦µé¾î¼
pong ¾²·¹µå¿¡¼ Å©¸®Æ¼Äü½¼Ç¿¡ µé¾î°¡±â À§Çؼ ¾î¶²
ºÎ°¡ÀûÀÎ ÀÛ¾÷ÀÌ ÀÖ´Ù°í ÇßÀ»¶§(¸Þ¸ð¸®ÃʱâÈ, ±âŸ ´Ù¸¥ ÇÔ¼ö
È£Ãâ°ú °°Àº, À§¿¡¼´Â sleep À¸·Î ´ë½ÅÇß´Ù), ¿ì¸®°¡
ÀǵµÇß´ø ¹Ù¿Í´Â ´Ù¸£°Ô ping °¡ ¸ÕÀú Å©¸®Æ¼Äü½¼Ç¿¡
ÁøÀÔÇÒ¼öµµ ÀÖ´Ù. ÀÌ·²°æ¿ì 2°³ÀÇ ¾²·¹µå´Â ±³Âø»óÅ¿¡
ºüÁö°Ô µÈ´Ù.
ping ¾²·¹µå°¡ Å©¸®Æ¼Äü½¼Ç¿¡ ¸ÕÀú ÁøÀÔÇßÀ»°æ¿ì
ping ¾²·¹µå´Â "ping" Ãâ·Â½ÃŰ°í ½Ã±×³ÎÀ» ¹ß»ý½Ãų
°ÍÀ̰í pong ¾²·¹µå°¡ "pong"¸¦ Ãâ·Â½ÃŰ°í ½Ã±×³ÎÀ»
¹ß»ý½Ãų¶§±îÁö ½Ã±×³Î´ë±â ÇÏ°Ô µÈ´Ù.
ping ¾²·¹µå°¡ ½Ã±×³Î´ë±â ÇÏ°Ô µÇ¸é, Å©¸®Æ¼Äü½¼Ç¿¡ ´ëÇÑ
¹ÂÅØ½º Àá±ÝÀÌ ÇØÁ¦µÊÀ¸·Î µÚ´Ê°Ô Å©¸®Æ¼Äü½¼Å³× ÁøÀÔÀ»
½ÃµµÇÏ´ø pong °¡ Å©¸®Æ¼Äü½¼Ç¿¡ ÁøÀÔÇϰí ping ¾²·¹µå¿¡¼ºÎÅÍ
½ÅÈ£°¡ ÀÖ´ÂÁö ±â´Ù¸®°Ô µÉ°ÍÀÌ´Ù. ±×·¯³ª ping ¾²·¹µå´Â À̹Ì
½ÅÈ£¸¦ ³¯·Á¹ö·ÈÀ½À¸·Î, pong ¾²·¹µå´Â °áÄÚ µµÂøÇÏÁö ¾ÊÀ»
½ÅÈ£¸¦ ±â´Ù¸®¸ç ¿µ¿øÈ÷ ½Ã±×³Î´ë±â ÇÏ°Ô µÉ°ÍÀÌ´Ù.
ÀÌ·±½ÄÀ¸·Î 2°³ÀÇ ¾²·¹µå´Â ±³Âø»óÅ¿¡ ºüÁ® ¹ö¸°´Ù.
ÀÌ ¹®Á¦´Â ¾²·¹µå°£ µ¿±âȸ¦ ÀÌ¿ëÇØ¼ ÇØ°áÇÒ¼ö ÀÖÀ¸¸ç,
À§ Äڵ忡¼´Â mutex Àá±Ý°ú, Á¶°Çº¯¼ö¸¦ ÀÌ¿ëÇØ¼
ÇØ°áÇϰí ÀÖ´Ù. ¹°·Ð ¾²·¹µå°£ µ¿±âȸ¦ À§Çؼ
»ç¿ëÇÒ¼ö ÀÖ´Â ¿ø½Ã?ÀûÀÎ ¹æ¹ýÀ¸·Î sleep ³ª usleep °°Àº
ÇÔ¼ö¸¦ È£ÃâÇÏ´Â ¹æ¹ýµµ ÀÖ±ä ÇÏÁö¸¸, ping ¾²·¹µå¿¡¼
Å©¸®Æ¼Äà ¼½¼Ç¿¡ ÁøÀÔÇϱâÀü 1ÃÊ Á¤µµ sleep À» ÁÖ´Â ½ÄÀ¸·Î
»ç¿ë°¡´ÉÇÏÁö¸¸ ÃßõÇÒ¸¸ÇÏÁø ¾Ê´Ù.
(°£È¤ °£´ÜÇÏ°Ô »ç¿ëÇÒ¼ö´Â À¸¸ç, °¡Àå È®½ÇÇÑ ¹æ¹ýÀ» Á¦°øÇØ
Áֱ⵵ ÇÑ´Ù)
pthread_attr_init´Â thread attribute °´Ã¼ÀÎ
attrÀ» µðÆúÆ® °ªÀ¸·Î ÃʱâÈ ½ÃŲ´Ù.
¼º°øÇÒ°æ¿ì 0À» µ¹·ÁÁÖ°í ½ÇÆÐÇÒ°æ¿ì -1 À» µÇµ¹·ÁÁØ´Ù.
pthread_attr_init¿¡ ÀÇÇØ »ý¼ºµÈ thread attribute °´Ã¼ÀÎ
attrÀ» Á¦°ÅÇÑ´Ù. Á¦°ÅµÈ attr À» ´Ù½Ã »ç¿ëÇϱâ À§Çؼ´Â
pthread_attr_init¸¦ ÀÌ¿ëÇØ¼ ´Ù½Ã ÃʱâÈ ÇØÁÖ¾î¾ß ÇÑ´Ù.
int pthread_attr_getscope(const pthread_attr_t *attr,
int *scope);
|
¾²·¹µå°¡ ¾î¶² ¿µ¿ª(scope)¿¡¼ ´Ù·ç¾îÁö°í ÀÖ´ÂÁö¸¦ ¾ò¾î¿À±â À§Çؼ »ç¿ëµÈ´Ù.
PTHREAD_SCOPE_SYSTEM°ú PTHREAD_SCOPE_PROCESS ÀÇ 2°¡Áö
¿µ¿ªÁß¿¡ ¼±ÅÃÇÒ¼ö ÀÖ´Ù. SYSTEM ¿µ¿ª ¾²·¹µå´Â user ¸ðµå ¾²·¹µå¶ó°í
ºÒ¸®¿ì¸ç, PROCESS ¾²·¹µå´Â Ä¿³Î¸ðµå ¾²·¹µå¶ó°í ºÒ¸®¿î´Ù.
¸®´ª½ºÀÇ °æ¿ì À¯Àú¸ðµå ¾²·¹µåÀε¥, Áï Ä¿³Î¿¡¼ ¾²·¹µå¸¦ ½ºÄÉÁ층ÇÏ´Â
¹æ½ÄÀÌ ¾Æ´Ñ ¾²·¹µå ¶óÀ̺귯¸®¸¦ ÅëÇØ¼ ¾²·¹µå¸¦ ½ºÄÉÁ층 ÇÏ´Â ¹æ½ÄÀ»
»ç¿ëÇÑ´Ù.
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
pthread_attr_t pattr;
int scope;
pthread_attr_init(&pattr);
pthread_attr_getscope(&pattr, &scope);
if (scope == PTHREAD_SCOPE_SYSTEM)
{
printf("user mode thread\n");
}
else if (scope == PTHREAD_SCOPE_PROCESS)
{
printf("Kernel mode thread\n");
}
return 1;
}
|
À§ ÇÁ·Î±×·¥À» ÄÄÆÄÀÏÇÑÈÄ Linux ¿¡¼ ½ÇÇà½Ã۸é "user mode thread"¸¦
Ãâ·ÂÇÏ°í ¼Ö¶ó¸®½º »ó¿¡¼ ½ÇÇà½Ã۸é "kernel mode thread"¸¦ Ãâ·ÂÇÑ´Ù.
¾²·¹µå°¡ ¾î¶² ¿µ¿ª(scope)¿¡¼ ÀÛµ¿ÇÏ°Ô ÇÒ°ÍÀÎÁö °áÁ¤Çϱâ À§Çؼ »ç¿ëÇÑ´Ù.
¸®´ª½ºÀÇ °æ¿ì Kernel mode ¾²·¹µå¸¦ Áö¿øÇÏÁö ¾ÊÀ½À¸·Î ¿ÀÁ÷ PTHREAD_SCOPE_SYSTEM
¸¸À» ¼±ÅÃÇÒ¼ö ÀÖ´Ù. ¹Ý¸é ¼Ö¶ó¸®½º´Â À¯Àú¸ðµå¿Í Ä¿³Î¸ðµåÁß ¼±ÅÃÀÌ °¡´ÉÇÏ´Ù.
pthread_attr_setscope.c
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
pthread_attr_t pattr;
int scope;
pthread_attr_init(&pattr);
pthread_attr_setscope(&pattr, PTHREAD_SCOPE_PROCESS);
pthread_attr_getscope(&pattr, &scope);
if (scope == PTHREAD_SCOPE_SYSTEM)
{
printf("user mode thread\n");
}
else if (scope == PTHREAD_SCOPE_PROCESS)
{
printf("Kernel mode thread\n");
}
return 1;
}
|
À§Äڵ忡¼ ¾²·¹µå°¡ Ä¿³Î ¸ðµå¿¡¼ ÀÛµ¿Çϵµ·Ï ÁöÁ¤À» Çß´Ù.
¸®´ª½º¿¡¼ ½ÇÇà½Ãų°æ¿ì¿¡´Â ºñ·Ï Ä¿³Î¸ðµå·Î ÁöÁ¤À» Çß´Ù°í ÇÏ´õ¶óµµ
À¯Àú¸ðµå ¾²·¹µå·Î ÀÛµ¿ÇÏ°Ô µÈ´Ù. ¼Ö¶ó¸®½ºÀÇ °æ¿ì¿¡´Â
setscope ·Î ÁöÁ¤ÇÑ´ë·Î Ä¿³Î¸ðµå¿¡¼ ÀÛµ¿ÇÏ°Ô µÈ´Ù.
int pthread_attr_getdetachstate(pthread_attr_t *attr,
int detachstate);
|
¾²·¹µå°¡ join °¡´ÉÇÑ »óÅÂ(PTHREAD_CREATE_JOINABLE) ÀÎÁö
detached »óÅÂÀÎÁö (PTHREAD_CREATE_DETACHED) ÀÎÁö¸¦
¾Ë¾Æ³½´Ù. ¾Ë¾Æ³½ °ªÀº ¾Æ±Ô¸ÕÆ® detachstate
¿¡ ÀúÀåµÈ´Ù.
±âº»Àº PTHREAD_CREATE_JOINABLE À̸ç,
pthread_detach¸¦ ÀÌ¿ëÇØ¼
»ý¼ºµÈ ¾²·¹µå¸¦ detach »óÅ·Π¸¸µé¾úÀ»°æ¿ì
¶Ç´Â pthread_attr_setdetachstateÇÔ¼ö¸¦
ÀÌ¿ëÇØ¼ ¾²·¹µå¸¦ detache »óÅ·Πº¯°æ½ÃÄ×À»°æ¿ì
PTHREAD_CREATE_DETACHED »óŰ¡ µÈ´Ù.
¿¹Á¦ : pthread_attr_getdetachstate.c
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
pthread_attr_t attr;
void *test(void *a)
{
int policy;
printf("Thread Create\n");
pthread_attr_getdetachstate(&attr, &policy);
if (policy == PTHREAD_CREATE_JOINABLE)
{
printf ("Join able\n");
}
else if (policy == PTHREAD_CREATE_DETACHED)
{
printf ("Detache\n");
}
}
int main()
{
int status;
pthread_t p_thread;
pthread_attr_init(&attr);
if (pthread_create(&p_thread, NULL, test, (void *)NULL) < 0)
{
exit(0);
}
pthread_join(p_thread, (void **)&status);
}
|
À§ÀÇ ÇÁ·Î±×·¥À» ½ÇÇà½ÃŰ¸é ºÐ¸í "Join able"¸¦ Ãâ·ÂÇÒ°ÍÀÌ´Ù.
int pthread_attr_setdetachstate(pthread_attr_t *attr,
int detachstate);
|
¾²·¹µåÀÇ »óŸ¦ PTHREAD_CREATE_JOINABLE ȤÀº
PTHREAD_CREATE_DETACHED »óÅ·Πº¯°æ½Ã۱â À§Çؼ »ç¿ëµÈ´Ù.
¾Æ·¡¿Í °°Àº ¹æ¹ýÀ¸·Î »ç¿ëÇÏ¸é µÈ´Ù.
pthread_attr_t attr;
...
// JOINABLE »óÅ·Πº¯°æÇϰíÀÚ ÇÒ¶§
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// DETACHED »óÅ·Πº¯°æÇϰíÀÚ ÇÒ¶§
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
¾²·¹µå°£ ÇÁ·Î¼¼½º¿Í ¾²·¹µå°£ ½Ã±×³Î Àü´Þ°ü·Ã APIµéÀÌ´Ù.
ÀÚ¼¼ÇÑ ³»¿ëÀº ¾²·¹µå¿Í ½Ã±×³ÎÀ» Âü°íÇϱ⠹ٶõ´Ù.
#include <pthread.h>
#include <signal.h>
int pthread_sigmask(int how, const sigset_t *newmask, sigset_t *oldmask);
|
¾²·¹µå¿¡¼ ½Ã±×³ÎÀº ¼·Î °øÀ¯µÈ´Ù. ±×·±ÀÌÀ¯·Î ¸¸¾à ÇÁ·Î¼¼½º¿¡
½Ã±×³ÎÀÌ Àü´ÞµÇ¸é ÇÁ·Î¼¼½º°¡ »ý¼ºµÈ ¸ðµç ¾²·¹µå·Î ½Ã±×³ÎÀÌ Àü´ÞµÈ´Ù.
±×·¯³ª ƯÁ¤ ¾²·¹µå¸¸ ½Ã±×³ÎÀ» ¹Þµµ·Ï ÇÏ°í ½ÍÀ» ¶§°¡ ÀÖÀ» °ÍÀÌ´Ù.
À̰æ¿ì ÀÌ ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¸é µÈ´Ù.
#include <pthread.h>
#include <signal.h>
int pthread_kill(pthread_t thread, int signo);
|
¾²·¹µå ½Äº°¹øÈ£ thread·Î signo
¹øÈ£ÀÇ ½Ã±×³ÎÀ» Àü´ÞÇÑ´Ù.
#include <pthread.h>
#include >signal.h>
int sigwait(const sigset_t *set, int *sig);
|
½Ã±×³Î Àü´ÞÀ» µ¿±âÀûÀ¸·Î ±â´Ù¸°´Ù.
|