ÃÑ ÆäÀÌÁö ¼ö : 3224
![]()
|
Facebook Joinc ±×·ì
Joinc QA »çÀÌÆ®
![]()
Tweet
joinc´Â Firefox¿Í chrome¿¡¼ Å×½ºÆ® Çß½À´Ï´Ù. IE¿¡¼´Â Å×À̺íÀÌ ±úÁö°Å³ª À̹ÌÁö°¡ º¸ÀÌÁö ¾ÊÀ» ¼ö ÀÖ½À´Ï´Ù. ƯÈ÷ ±¸±Û DocsÀ̹ÌÁöÀÇ °æ¿ì ¿¢¹Úó¸®µÉ ¼ö ÀÖ½À´Ï´Ù. 1 ¸ñ Àû
1.1 Code 1/* ÀÚ¹ÙÀÇ ±×°Í°ú ºñ½ÁÇÑ ¾²·¹µå °´Ã¼ Ŭ·¡½º ¶Ç´Â ÀÎÅÍÆäÀ̽º ±¸Çö */
/* µ¥¸óÀ¸·Î ½ÇÇà½Ã stop ¿¡ ÀÇÇÑ SIGTERM ½ÅÈ£¿¡ ¾²·¹µå°´Ã¼ÀÇ ¼Ò¸êÀÚ È£Ãâó¸® */
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
using namespace std;
class tClass {
private :
pthread_t pt;
int* a;
void prn(void) {
cout << "This is private method " << *a << endl;
}
// ¾Æ·¡´Â ¾²·¹µå¿¡¼ ½ÇÁ¦ »ç¿ëµÉ ¸ÞÀÎ ÇÔ¼öÀÌ´Ù. ¼ø¼ö°¡»óÇÔ¼ö·Î Á¤ÀÇÇÏ¿© ÀÌ Å¬·¡½º¸¦
// ÀÎÅÍÆäÀ̽ºÈÇÏ¿© »ó¼Ó¹Þ´Â Ŭ·¡½º¿¡¼ ¾²·¹µåÇÔ¼ö·Î ÇÊ¿äÇÑ ÀÛ¾÷À» Á¤ÀÇÇÏ¿© »ç¿ëÇÒ
// ¼ö µµ ÀÖ°Ú´Ù. ±×·²¶© protected ȤÀº public ¸â¹ö·Î ¸¸µé¾î³õ¾Æ¾ß »ó¼Ó¹Þ´Â Ŭ·¡½º¿¡¼
// ÀÌ ¼ø¼ö°¡»óÇÔ¼öÀÇ ³»¿ëÀ» Á¤ÀÇÇÏ¿© »ç¿ëÇÒ ¼ö°¡ ÀÖ°Ú´Ù. ¶ÇÇÑ pthread_create¸¦ »ý¼ºÀÚ¿¡¼
// È£ÃâÇÏ¸é »ó¼Ó¹ÞÀº Ŭ·¡½º¿¡¼ ³»¿ëÀ» Á¤ÀÇÇØ³õÀº tFunc °¡ È£ÃâµÉ ¼ö ¾øÀ¸¹Ç·Î »ý¼ºÀÚ¿¡¼±
// pthread_create¸¦ ÇÏÁö ¾Ê°í µû·Î ¸â¹öÇÔ¼ö¸¦ µÎ¾î °Å±â¼ ¾²·¹µåÈ£ÃâÀ» ÇØ¾ßÇÑ´Ù.
void tFunc(void) {
*a = 1;
prn();
while (1) {
cout << "This is thread method " << (*a)++ << endl;
sleep(1);
}
}
static void* callThread(void* arg); // ½ÇÁ¦ pthread_create¿¡ »ç¿ëµÇ´Â ¸Þ¼Òµå
public :
tClass(void) {
cout << "This is constructor" << endl;
a = new int;
pthread_create(&pt, NULL, callThread, this);
// static ¸â¹ö¸Þ¼Òµå´Â static¸â¹ö¿¡¸¸ Á¢±Ù°¡´ÉÇϹǷΠÀÌ Å¬·¡½ºÀÇ °´Ã¼ÁÖ¼Ò¸¦
// ÀÎÀÚ·Î ³Ñ°Ü private¸¦ Æ÷ÇÔÇÑ ¸ðµç ¸â¹ö¸¦ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù.
}
~tClass(void) {
int i;
// mainÀÇ Á¾·á½Ã Á¾¼Ó¾²·¹µå¸¦ ¸ÕÀú Á¾·á½ÃŰ´ÂÁö ÀνºÅϽºµéÀÇ ¸Þ¸ð¸®ÇØÁ¦¸¦
// ¸ÕÀú ½ÃŰ´ÂÁö ¾Ë¾Æº¸±â À§ÇÏ¿© ·çÇÁ¸¦ µ¹¸²
for (i = 0; i < 3; i++) {
cout << "This is destructor" << endl;
sleep(1);
}
delete a;
}
};
// static ¸â¹öº¯¼ö´Â Ŭ·¡½º ¼±¾ð ¹Û¿¡¼ Á¤ÀÇÇØ¾ßÇÔ
void* tClass :: callThread(void* arg) {
tClass* tp;
tp = (tClass*) arg;
tp->tFunc(); // ¾²·¹µåÀÛ¾÷À» ÇÒ ¸Þ¼Òµå¸¦ ½ÇÇà½ÃŲ´Ù
// ÀÌ °÷¿¡¼ Á÷Á¢ ¾²·¹µåÀÛ¾÷µéÀ» ÇÏ¿©µµ µÇ°ÚÀ¸³ª, Ŭ·¡½º¸â¹ö¸¦ »ç¿ëÇÒ¶§¸¶´Ù
// Æ÷ÀÎÅ͸¦ ÅëÇØ Á¢±ÙÇØ¾ß ÇϹǷΠ±ò²ûÇÏÁö ¸øÇϸç ÀÌ Å¬·¡½º¸¦ ÀÎÅÍÆäÀ̽ºÈÇÏÁö ¸øÇÑ´Ù
}
int main () {
int i;
tClass tc;
for (i = 0; i < 3; i++) {
cout << "This is main" << endl;
sleep(1);
}
cout << "main exit" << endl;
return (1);
}
1.2 Code 2
/* ÀÚ¹ÙÀÇ ±×°Í°ú ºñ½ÁÇÑ ¾²·¹µå °´Ã¼ Ŭ·¡½º ¶Ç´Â ÀÎÅÍÆäÀ̽º ±¸Çö */
/* µ¥¸óÀ¸·Î ½ÇÇà½Ã stop ¿¡ ÀÇÇÑ SIGTERM ½ÅÈ£¿¡ ¾²·¹µå°´Ã¼ÀÇ ¼Ò¸êÀÚ È£Ãâó¸® */
#include <signal.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
using namespace std;
class tClass {
private :
int* a;
void prn(void) {
cout << "This is private method " << *a << endl;
}
// ¾²·¹µåÇÔ¼öÀÌ´Ù. ¼ø¼ö°¡»óÇÔ¼ö·Î Á¤ÀÇÇÏ¿© ÀÌ Å¬·¡½º¸¦ ÀÎÅÍÆäÀ̽ºÈÇÏ¿©
// »ó¼Ó¹Þ´Â Ŭ·¡½º¿¡¼ ¾²·¹µåÇÔ¼ö·Î ÇÊ¿äÇÑ ÀÛ¾÷À» Á¤ÀÇÇÏ¿© »ç¿ëÇÒ ¼ö µµ ÀÖ°Ú´Ù.
void tFunc(void) {
*a = 1;
prn();
while (1) {
cout << "This is thread method " << (*a)++ << endl;
sleep(1);
}
}
static void* callThread(void* arg); // ½ÇÁ¦ pthread_create¿¡ »ç¿ëµÇ´Â ¸Þ¼Òµå
public :
pthread_t pt; // main ¿¡¼ÀÇ pthread_cacel È£ÃâÀ» À§ÇØ publicÀ¸·Î ÇÔ
tClass(void) {
cout << "This is constructor" << endl;
a = new int;
pthread_create(&pt, NULL, callThread, this);
// static ¸â¹ö¸Þ¼Òµå´Â static¸â¹ö¿¡¸¸ Á¢±Ù°¡´ÉÇϹǷΠÀÌ Å¬·¡½ºÀÇ °´Ã¼ÁÖ¼Ò¸¦
// ÀÎÀÚ·Î ³Ñ°Ü private¸¦ Æ÷ÇÔÇÑ ¸ðµç ¸â¹ö¸¦ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇÑ´Ù.
}
~tClass(void) {
int i;
// mainÀÇ Á¾·á½Ã Á¾¼Ó¾²·¹µå¸¦ ¸ÕÀú Á¾·á½ÃŰ´ÂÁö ÀνºÅϽºµéÀÇ ¸Þ¸ð¸®ÇØÁ¦¸¦
// ¸ÕÀú ½ÃŰ´ÂÁö ¾Ë¾Æº¸±â À§ÇÏ¿© ·çÇÁ¸¦ µ¹¸²
for (i = 0; i < 3; i++) {
cout << "This is destructor" << endl;
sleep(1);
}
delete a;
}
};
// static ¸â¹ö ¸Þ¼Òµå´Â Ŭ·¡½º ¼±¾ð ¹Û¿¡¼ Á¤ÀÇÇØ¾ßÇÔ
void* tClass :: callThread(void* arg) {
tClass* tp;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
tp = (tClass*) arg;
tp->tFunc(); // ¾²·¹µåÀÛ¾÷À» ÇÒ ¸Þ¼Òµå¸¦ ½ÇÇà½ÃŲ´Ù
// ÀÌ °÷¿¡¼ Á÷Á¢ ¾²·¹µåÀÛ¾÷µéÀ» ÇÏ¿©µµ µÇ°ÚÀ¸³ª, Ŭ·¡½º¸â¹ö¸¦ »ç¿ëÇÒ¶§¸¶´Ù
// Æ÷ÀÎÅ͸¦ ÅëÇØ Á¢±ÙÇØ¾ß ÇϹǷΠ±ò²ûÇÏÁö ¸øÇϸç ÀÌ Å¬·¡½º¸¦ ÀÎÅÍÆäÀ̽ºÈÇÏÁö ¸øÇÑ´Ù
}
tClass tc; // sigHandler¿¡¼ÀÇ ÀÛ¾÷À» À§ÇØ Àü¿ªÀ¸·Î ¼±¾ð
void sigHandler(int sig) {
cout << "Got signal " << sig << endl;
pthread_cancel(tc.pt); // ¾²·¹µå Á¾·á
pthread_join(tc.pt, NULL);
cout << "Signal Handler exit" << endl;
exit(EXIT_SUCCESS);
// °´Ã¼ÀÇ ¼Ò¸êÀÚ´Â mainÀÌ Á¾·áµÇ¸é¼ ÀÚµ¿À¸·Î È£ÃâµÈ´Ù. À̰͵µ Á÷Á¢ È£ÃâÇÒ·Á¸é
// tClass* tc·Î ¼±¾ðÇÏ¿© newÇÏ¿© »ç¿ëÇÑ ÈÄ ¿©±â¼ delete ÇÏ¸é µÈ´Ù
}
int main () {
signal(SIGTERM, sigHandler);
while (1) {
cout << "This is main" << endl;
sleep(1);
}
}
1.3 ¹ÌºñÁ¡
1.4 Àâ ´ã
2 ¾²·¹µå °´Ã¼ÀÇ ÀÚ¿ø Á¤¸®
¾²·¹µå¸¦ Ŭ·¡½º¸¦ ÀÌ¿ëÇØ¼ °´Ã¼È ÇÒ°æ¿ì, ¾²·¹µå¸¦ detach »óÅ·Π½ÇÇà½ÃŰ´Â °æ¿ì°¡ ¸¹´Ù. ÀÌ °æ¿ì pthread_joinc()ÇÔ¼ö¸¦ ÀÌ¿ëÇÏÁö ¾Ê°Ô µÊÀ¸·Î, ºÎ¸ð ¾²·¹µå´Â Àڽľ²·¹µåÀÇ »óŸ¦ Á¤È®ÇÏ°Ô ¾Ë±â Èûµé°í, ¶§¹®¿¡ ÀÚ¿øÁ¤¸®¿¡ ¹®Á¦°¡ ¹ß»ýÇÒ ¼ö ÀÖ´Ù. ÀÚ½Ä ¾²·¹µå°¡ ÀÚ½ÅÀÇ Á¾·á½ÃÁ¡À» ¸íÈ®È÷ ¾Ë°í ÀÖ´Ù¸é, ¼Ò¸êÀÚ¸¦ ÀÌ¿ëÇØ¼ ÇÊ¿äÇÑ ÇØÁ¦¸¦ ÇÒ ¼ö ÀÖ°ÚÁö¸¸, pthread_cancel()µî ºñµ¿±âÀûÀÎ ¹æ¹ýÀ¸·Î Á¾·á ½Ãų°æ¿ì ¹®Á¦°¡ µÉ ¼ö ÀÖ´Ù.
¿©·¯°¡Áö ¹æ¹ýÀÌ ÀÖ°ÚÀ¸³ª, ÇÊÀÚ´Â pthread_cleanup_push()¿Í pthread_cleanpu_pop() ÇÔ¼ö¸¦ ÀÌ¿ëÇØ¼ ÀÌ ¹®Á¦¸¦ ÇØ°áÇß´Ù. 2.1 Å×½ºÆ® ¼¹ö ÇÁ·Î±×·¥
°£´ÜÇÑ Å×½ºÆ® ¼¹ö ÇÁ·Î±×·¥À» ¸¸µé¾î º¸µµ·Ï ÇϰڴÙ. ÀÌ ÇÁ·Î±×·¥Àº echo Ŭ¶óÀ̾ðÆ®ÀÇ thread ¹öÁ¯ÀÌ´Ù. ¿¬°áÀÌ µé¾î¿À¸é ºÎ¸ð¾²·¹µå´Â »õ·Î¿î Àڽľ²·¹µå¸¦ »ý¼ºÇÑ´Ù. ¶ÇÇÑ ºÎ¸ð¾²·¹µå´Â select()¸¦ ÀÌ¿ëÇÏ¿© Ç¥ÁØÀÔ·ÂÀ» ±â´Ù¸°´Ù. ÀÌ Ç¥ÁØÀÔ·ÂÀ» ÅëÇØ¼ ƯÁ¤ Àڽľ²·¹µå Á¾·á³ª Àڽľ²·¹µå »óÅ Á¤º¸Á¦°øµî°ú °°Àº ÀÏÀ» ÇÏ°Ô µÈ´Ù.
+--------------+
+------> | child Thread |----+
| +--------------+ | +------------------+
+-------------+ accept() | +--------------+ | | CleanUp Function |
| Main Thread |-----------+------> | child Thread |----+---| + delete this |
+-------------+ | +--------------+ | +------------------+
| | +--------------+ | |
| +------> | child Thread |----+ |
| +--------------+ |
| pthread_cancel() |
| -------------------------> pthread_cleanup_push()----->>---+
|
---------------------- STDIN
Thread Information
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <signal.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <map>
using namespace std;
#define MAXLEN 256
map<int, pthread_t> Cinfo;
class tClass {
private :
pthread_t pt;
int sockfd;
char *buf;
static void* callThread(void* arg);
// ¾²·¹µå Á¾·áÇÔ¼ö
// ÀÚ½ÅÀ» delete ÇÑ´Ù.
static void clean_up(void *arg)
{
delete (tClass *)arg;
}
public :
// Client¿Í Åë½ÅÀ» ´ã´çÇÏ´Â ÇÔ¼ö·Î ¾²·¹µå ÇÔ¼öÀÎ callThread¿¡¼
// È£ÃâÇÑ´Ù.
void tFunc(void)
{
int readn;
buf = (char *)malloc(MAXLEN);
// ¾²·¹µå Á¾·áÇÔ¼öÀÎ clean_upÀ» È£ÃâÇÑ´Ù.
// ÀÎÀÚ·Î ¾²·¹µå ÀÚ½ÅÀÇ Æ÷ÀÎÅ͸¦ ³Ñ±ä´Ù.
pthread_cleanup_push(clean_up, (void *)this);
while (1)
{
memset(buf, 0x00, MAXLEN);
readn = read(sockfd, buf, MAXLEN);
if(readn <=0)
{
perror("Socket Read Error:");
break;
}
write(sockfd, buf, strlen(buf));
}
pthread_exit((void *)NULL);
// ¾²·¹µå Á¾·áÇÔ¼ö¸¦ pop½ÃŲ´Ù.
pthread_cleanup_pop(0);
}
tClass(int sfd)
{
sockfd = sfd;
buf = NULL;
pt = 0;
pthread_attr_t attr;
// ¾²·¹µå¸¦ Detached »óÅ·Π¸¸µç´Ù.
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&pt, &attr, callThread, this);
}
// ¸¸µé¾îÁø ¾²·¹µå°´Ã¼ÀÇ pthread_id¸¦ ¸®ÅÏÇÑ´Ù.
pthread_t tClassId()
{
return pt;
}
// ¼Ò¸êÀÚ·Î
// ¾²·¹µå ÀÚ¿ø°ú Àü¿ª ÀڷᱸÁ¶¸¦ Á¤¸®ÇÑ´Ù.
~tClass(void)
{
map<int, pthread_t>::iterator mi;
if(buf)
free(buf);
if (sockfd)
{
mi = Cinfo.find(sockfd);
if (mi!=Cinfo.end())
{
Cinfo.erase(mi);
}
close(sockfd);
}
printf("Thread Close\n");
}
};
void* tClass :: callThread(void* arg)
{
tClass* tp;
tp = (tClass*) arg;
tp->tFunc();
}
int main (int argc, char **argv)
{
pthread_t pthread;
struct sockaddr_in clientaddr, serveraddr, myaddr;
int maxfd = 0;
fd_set fd_w;
struct timeval timeout;
class tClass *ClientClass;
int server_sockfd, client_sockfd, client_len;
if (argc != 2)
{
printf("Usage : %s [PORT]\n", argv[0]);
return 1;
}
if ((server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket error:");
return 1;
}
bzero(&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons(atoi(argv[1]));
if (bind(server_sockfd, (struct sockaddr *)&serveraddr,
sizeof(serveraddr)) == -1)
{
perror("bind error:");
return 1;
}
if (listen(server_sockfd, 5) == -1)
{
perror("listen error :");
return 1;
}
client_len = sizeof(clientaddr);
char buf[MAXLEN];
// Main Thread
// Accept ÀÔ·ÂÀÎ °æ¿ì »õ·Î¿î ¾²·¹µå¸¦ »ý¼º½Ã۰í
// Ç¥ÁØÀÔ·ÂÀÎ °æ¿ì ÀÔ·ÂµÈ ¸í·ÉÀ» È®ÀÎÇØ¼
// showÀϰæ¿ì ¾²·¹µå Á¤º¸¸¦ º¸¿©ÁÖ°í
// killÀÏ °æ¿ì ÇØ´ç ¾²·¹µå¸¦ Á¾·á½ÃŲ´Ù.
// kill Àº ÇϳªÀÇ ÀÎÀÚ¸¦ °¡Áø´Ù. ÀÎÀÚ´Â ¼ÒÄÏÁöÁ¤¹øÈ£´Ù.
while(1)
{
FD_ZERO(&fd_w);
FD_SET(0, &fd_w);
FD_SET(server_sockfd, &fd_w);
select(server_sockfd + 1, &fd_w, (fd_set *)0, (fd_set*)0, NULL);
if(FD_ISSET(server_sockfd,&fd_w))
{
client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr,
(socklen_t *)&client_len);
ClientClass = new tClass(client_sockfd);
Cinfo[client_sockfd] = ClientClass->tClassId();
}
else if(FD_ISSET(0, &fd_w))
{
memset(buf, 0x00, MAXLEN);
read(0, buf, MAXLEN);
if(strncmp(buf, "show", 4) == 0)
{
map<int, pthread_t>::iterator mi;
mi = Cinfo.begin();
printf("NUM\tThread ID\tClient Address\n");
while(mi != Cinfo.end())
{
getsockname(mi->first, (struct sockaddr *)&myaddr, (socklen_t *)&client_len);
printf("%d\t%u\t%s\n", mi->first, mi->second, inet_ntoa(myaddr.sin_addr));
*mi++;
}
printf("=============================\n");
}
if (strncmp(buf, "kill", 4) == 0)
{
map<int, pthread_t>::iterator mi;
mi = Cinfo.find(atoi(buf+5));
if (mi == Cinfo.end())
{
printf("Not Found Thread\n");
}
else
{
printf("Kill Thread %u\n", mi->second);
pthread_cancel(mi->second);
}
}
}
else
{
printf("Unknown\n");
}
}
}
´ÙÀ½Àº Å×½ºÆ® °á°ú´Ù.# ./thclass 2222 show NUM Thread ID Client Address 4 3083553712 127.0.0.1 5 3075161008 10.14.20.169 ============================= kill 5 Kill Thread 3075161008 Thread Close show NUM Thread ID Client Address 4 3083553712 127.0.0.1 ============================= |
|
|
|
EmailÀ» ±âÀÔÇϸé, ´ñ±ÛÀÌ ¸ÞÀÏ·Î Àü´ÞµË´Ï´Ù. |
|