#ifndef __ZCPPMAIN__PROCESS_LINUX_H__ #define __ZCPPMAIN__PROCESS_LINUX_H__ #include "ZCppMain/ZMainHead.H" #include #include #include #include #include #include #include #include #include #include namespace ZNsMain { /*//////////////////////////////////////////////////////////////////////// ¡á ´ëºÎºÐÀÇ ¾²·¹µå ÇÔ¼ö´Â ¼º°øÇϸé 0 À» ¹ÝȯÇϴµ¥ ÀÌ °ªÀ» enum ÁöÁ¤ÇÑ´Ù. ////////////////////////////////////////////////////////////////////////*/ namespace ZNsEnum { // ¾²·¹µå °ü·Ã ÇÔ¼ö°¡ ¿¡·¯ÀÏ °æ¿ì¿¡´Â Á¤Ã¥¿¡ µû¶ó, ZEThread_Invalid ÀÌ¿ÜÀÇ °ªÀ» ¹ÝȯÇÒ ¼öµµ ÀÖ´Ù. enum ZEThread { ZEThread_OK =0 , ZEThread_Invalid=EINVAL , // ¾²·¹µå °ü·Ã ÇÔ¼ö ¿¡·¯. ZEThread_TimeOut=ETIMEDOUT };/* enum ZEThread*/ /*//////////////////////////////////////// ¡á barrier ÀÇ ´ëÇ¥ÀûÀÎ ¹Ýȯ°ª. ¡á barrier ¿¡·¯¸¦ üũÇÒ ¶§ BarrierClass VO_BarrierClass; if(VO_BarrierClass.Init()==ZEBarrier_NO) { // some code } ·Î ÇÏÁö ¸»°í. if(VO_BarrierClass.Init()!=ZEBarrier_OK) { // some code } ·Î ÇØ¾ß ¾ÈÀüÇÏ´Ù. ////////////////////////////////////////*/ enum ZEBarrier { ZEBarrier_NO = -1, ZEBarrier_OK = 0 };/* enum ZEBarrier*/ }/* namespace ZNsEnum*/ /*///////////////////////////////////////////////////////////////////////////////////// ¡á ¸®´ª½º¿¡¼­ pthread ¶óÀ̺귯¸®¿¡ ¸µÅ©¸¦ °É¾îÁÙ °Í. ¡á ÇÑÄÄ º£Æ÷ÆÇ 3.0 ÀÇ °æ¿ì sys/sem.h ¿¡´Â ´ÙÀ½°ú °°Àº ¼³¸íÀÌ ³ª¿Í ÀÖ´Ù. The user should define a union like the following to use it for arguments for `semctl'. union semun { int val; <= value for SETVAL struct semid_ds *buf; <= buffer for IPC_STAT & IPC_SET unsigned short int *array; <= array for GETALL & SETALL struct seminfo *__buf; <= buffer for IPC_INFO }; Previous versions of this file used to define this union but this is incorrect. One can test the macro _SEM_SEMUN_UNDEFINED to see whether one must define the union or not. #define _SEM_SEMUN_UNDEFINED 1 ¡á IPC object ÀÇ Ç÷¡±×´Â IPC_CREAT, IPC_EXCL, 0 ÀÇ ¼¼ °ªÁßÀÇ ÇϳªÀ̸ç, 0 À̸é ÇØ´ç µ¿ ±âÈ­ object °¡ Á¸ÀçÇÒ ¶§¸¸ ¿¬´Ù. ÆÄÀÏ¿¡ ÀÖ´Â ¼¼¸¶Æ÷¾î ÇÔ¼ö´Â ÇÁ·Î¼¼½ºÀÇ °æ¿ì¿¡´Â Áö¿øµÇÁö ¾Ê°í ÀÖ´Ù. ±×·¡¼­ ÇÁ·Î¼¼½ºÀÇ °æ¿ì¿¡´Â ÀÇ ¼¼¸¶Æ÷¾î ÇÔ¼ö¸¦ ½á¾ß ÇÑ´Ù. -- 2004-07-12 /////////////////////////////////////////////////////////////////////////////////////*/ union semun { int val ; // value for SETVAL struct semid_ds* buf ; // buffer for IPC_STAT & IPC_SET unsigned short int* array; // array for GETALL & SETALL struct seminfo* __buf ; // buffer for IPC_INFO };/* union semun*/ /*////////////////////////////////////////////////////////////////// ¡á À©µµ¿ì¿¡¼­´Â µ¿±âÈ­ object ¿¡ À̸§À» ºÎ¿©ÇÒ ¼ö Àִµ¥, ¸®´ª½º¿¡ ¼­´Â ¼ýÀÚ۸¸ ºÎ¿©ÇÒ ¼ö ÀÖ´Ù. ±×·¡¼­ ȣȯÀ» À§ÇÏ¿© À̸§À¸·ÎºÎÅÍ Å°¸¦ À¯ÃßÇÏ´Â ÇÔ¼ö¸¦ ¸¸µé¾ú´Ù. ÆÄÀÏ À̸§À» ¾È´Ù¸é ftok() ÇÔ¼ö key_t ftok(const char *path, int id); ¸¦ »ç¿ëÇÏ´Â °Íµµ ¹æ¹ýÀÌ´Ù. //////////////////////////////////////////////////////////////////*/ static inline long ZfGetKeyNum(const char* const AP_Name) { int VI_Index =-1 ; long VL_KeyID = 1 ; if(AP_Name!=0) { while(AP_Name[++VI_Index]!=0) { VL_KeyID += AP_Name[VI_Index]*(VI_Index+1) ; }/* while(AP_Name[++VI_Index]!=0)*/ }/* if(AP_Name!=0)*/ return VL_KeyID; }/* static inline long ZfGetKeyNum(const char* const AP_Name)*/ /*///////////////////////////////////////////////////////////////////////////// ¡á ½Ã±×³ÎÀº ½×ÀÌÁö ¾Ê´Â´Ù. Áï µ¿ÀÏÇÑ À̺¥Æ®°¡ ¿¬À̾ ´Ù¼¸ ¹ø ¹ß»ýÇß´Ù°í ÇØ¼­ ÇÁ·Î¼¼¼­¿¡°Ô µ¿ÀÏÇÑ ½Ã±×³ÎÀ» ´Ù¼¸ ¹ø Àü´ÞÇØ ÁÖÁö ¾Ê´Â´Ù. ÀÌ·¯ÇÑ ¹®Á¦Á¡Àº sa_mask ¸¦ ÅëÇØ ÇØ°áÇÒ ¼ö ÀÖ´Ù. sa_mask ¿¡ ¼³Á¤µÈ ½Ã±×³ÎµéÀº µ¿ÀÏÇÑ À̺¥Æ®°¡ ¿¬ÀÌÀ̼­ ´Ù¼¸¹ø ¹ß»ýÇÏ´Â °æ¿ì ¼øÂ÷ÀûÀ¸·Î ½Ã±×³ÎÀ» ¹ß»ý½ÃŲ´Ù. Áï ù¹øÂ° ½Ã±× ³ÎÀÌ Ã³¸®µÇ´Â µ¿¾È ³ª¸ÓÁö ½Ã±×³ÎµéÀº ºí·ÎÅ· »óÅ¿¡ ÀÖ°Ô µÈ´Ù. -- TCP/IP ¼ÒÄÏ ÇÁ·Î±×·¡¹Ö (À±¼º¿ì Àú) 245 Page ¡á Áß¿ä Ansi, Posix ½Ã±×³Î Á¤ÀÇ #define SIG_ERR ((__sighandler_t) -1) // Error return. #define SIG_DFL ((__sighandler_t) 0) // Default action. #define SIG_IGN ((__sighandler_t) 1) // Ignore signal. #define SIGHUP 1 // Hangup (POSIX) #define SIGINT 2 // Interrupt (ANSI) #define SIGQUIT 3 // Quit (POSIX) #define SIGILL 4 // Illegal instruction (ANSI) #define SIGTRAP 5 // Trace trap (POSIX) #define SIGABRT 6 // Abort (ANSI) #define SIGFPE 8 // Floating-point exception (ANSI) #define SIGKILL 9 // Kill, unblockable (POSIX) #define SIGUSR1 10 // User-defined signal 1 (POSIX) #define SIGSEGV 11 // Segmentation violation (ANSI) #define SIGUSR2 12 // User-defined signal 2 (POSIX) #define SIGPIPE 13 // Broken pipe (POSIX) #define SIGALRM 14 // Alarm clock (POSIX) #define SIGTERM 15 // Termination (ANSI) #define SIGSTKFLT 16 // Stack fault #define SIGCHLD 17 // Child status has changed (POSIX) #define SIGCONT 18 // Continue (POSIX) #define SIGSTOP 19 // Stop, unblockable (POSIX) #define SIGTSTP 20 // Keyboard stop (POSIX) #define SIGTTIN 21 // Background read from tty (POSIX) #define SIGTTOU 22 // Background write to tty (POSIX) #define SIGSYS 31 // Bad system call #define SIGUNUSED 31 ¡Þ SIGHUP - Å͹̳ΠÀÎÅÍÆäÀ̽º¿¡ ÀÇÇØ ¿¬°áÀÇ ´ÜÀýÀÌ °¨ÁöµÇ¸é ÇØ´ç Á¦¾î Å͹̳ΰú ¿¬°áµÈ Á¦¾î ÇÁ·Î¼¼½º(¼¼¼Ç ¸®´õ)¿¡°Ô Àü´Þ - ¼¼¼Ç ¸®´õ°¡ Á¾·áÇßÀ» ¶§µµ ¹ß»ýÇϴµ¥ À̶§´Â foreground ÇÁ·Î¼¼½º ±×·ì³»ÀÇ ¸ðµç ÇÁ·Î¼¼½ºµé¿¡°Ô Àü´Þ - SIGHUP ½Ã±×³ÎÀº ¿ø·¡ ¸ðµ© ¿¬°á ²÷±è µîÀÇ ½Ã¸®¾ó ¶óÀÎÀÌ ²÷¾îÁö¸é ¹ß»ýÇÏ´Â ½Ã±×³ÎÀÌ´Ù. - À̸§ ÀÖ´Â ½Ã½ºÅÛ µ¥¸óµéÀº SIGHUP ½Ã±×³ÎÀ» configure fileÀ» ´Ù½Ã ÀоîµéÀÌ´Â µîÀÇ ÃʱâÈ­ ½ÅÈ£·Î ÇØ¼®ÇÑ´Ù. . bootp(8), gated(8), inetd(8), mountd(8), named(8), nfsd(8), ypbind(8) . pppd(8) ó·³ SIGHUPÀ» ¿ø·¡ÀÇ Àǵµ¿¡ Ãæ½ÇÇÏ°Ô ¼¼¼Ç Á¾·áÀÇ ¶æÀ¸·Î ¹Þ¾ÆµéÀÌ´Â »ç·Êµµ °£È¤ Àִµ¥, ¿ä»õ´Â º¸ÆíÀûÀ¸·Î ÀÌ ¿ªÇÒÀ» SIGTERMÀÌ ¸Ã´Â´Ù. . daemonÀº Á¦¾î ´Ü¸»±â ¾øÀÌ µ¹±â ¶§¹®¿¡ kernel·ÎºÎÅÍ SIGHUP ½ÅÈ£¸¦ ¼ö½ÅÇÏÁö ¸øÇÑ´Ù. ±×·¯¹Ç·Î ¸¹Àº daemonÀº ÀÌ ½ÅÈ£¸¦ daemonÀÇ ±¸¼º ÆÄÀÏÀÌ º¯°æµÇ¾î daemonÀÌ ±× ÆÄÀÏÀ» »õ·Î Àоî¾ß µÈ´Ù´Â °ÍÀ» ¾Ë·ÁÁÖ´Â °ü¸®ÀڷκÎÅÍÀÇ ÅëÁö·Î »ç¿ëÇÑ´Ù. . daemonÀÌ ¼ö½ÅÇÒ ¼ö ¾ø´Â ´Ù¸¥ µÎ °³ÀÇ ½ÅÈ£·Î SIGINT¿Í SIGWINCH°¡ ÀÖ°í À̵鵵 ¿ª½Ã ¾î¶² º¯È­¸¦ daemon¿¡°Ô ÅëÁöÇϱâ À§ÇØ »ç¿ëµÉ ¼ö ÀÖ´Ù. ¡Þ SIGINT - ÀÎÅÍ·´Æ® Ű (DELETE ¶Ç´Â Control-C)°¡ ´­·ÈÀ» ¶§ ¹ß»ý ¡Þ SIGQUIT - Control-backslash ¿¡ ÀÇÇØ ¹ß»ý ¡Þ SIGCHLD - ÇÁ·Î¼¼½º°¡ Á¾·áÇϰųª Á¤ÁöÇϸé, ºÎ¸ð ÇÁ·Î¼¼½º¿¡°Ô Àü´ÞµÈ´Ù. - ºÎ¸ð ÇÁ·Î¼¼½º´Â wait() ½Ã½ºÅÛ ÄÝÀ» »ç¿ëÇÏ¿© ¹«½¼ ÀÏÀÌ ÀϾ´ÂÁö ¾Ë¾Æº»´Ù. - ÀÌ ½Ã±×³Î¿¡ ´ëÇÑ default 󸮴 ¹«½ÃÇÏ´Â °ÍÀÌ´Ù. Áï ÇÁ·Î¼¼½º°¡ ÀÌ ½ÅÈ£¸¦ ¹ÞÀ¸·Á°í ÇÒ ¶§¸¸ Àü´ÞµÈ´Ù. ¡Þ SIGSEGV - À¯È¿ÇÏÁö ¾ÊÀº °¡»ó ¸Þ¸ð¸® ÁÖ¼Ò¸¦ ÂüÁ¶Çϰųª »ç¿ë ±ÇÇÑÀÌ ¾ø´Â ¸Þ¸ð¸®¿¡ Á¢±ÙÇÒ ¶§ ÇÁ·Î¼¼½º·Î Àü´ÞµÈ´Ù. ¡Þ SIGTERM - kill ¸í·É¿¡ ÀÇÇØ ±âº»ÀûÀ¸·Î ¹ß»ý ¡Þ SIGKILL - "±Ø´ÜÀÇ Á¶Ä¡(extreme prejudice)"·Î ÇÁ·Î±×·¥À» Á¾·áÇÏ´Â µ¥ »ç¿ëµÈ´Ù. - ½Ã±×³Î catch Çϰųª ¹«½ÃÇÒ ¼ö ¾ø´Ù. ¡Þ SIGALRM - alarm()À̳ª setitimer() ½Ã½ºÅÛ ÄÝ·Î ¼³Á¤ÇÑ ¾Ë¶÷ ½Ã°£ÀÌ Ãʰú ÇßÀ» ¶§ ÇÁ·Î¼¼½º·Î Àü´ÞµÈ´Ù. ¡Þ SIGTSTP - Control-Z Ű¿¡ ÀÇÇØ ¹ß»ý - ±âº» ó¸® ¹æ¹ýÀº SIGCONT ½ÅÈ£¸¦ ¹ÞÀ» ¶§±îÁö ÇÁ·Î¼¼½º¸¦ Áß´ÜÇÑ´Ù. ¡Þ SIGCONT - Á¤ÁöÇÑ ÇÁ·Î¼¼½º¸¦ °è¼Ó ½ÇÇà½ÃŰ·Á ÇÒ ¶§ ¹ß»ý - ÀÌ ½ÅÈ£´Â ¹ÞÀ» ¼ö ÀÖÁö¸¸ ºí·ÏÇϰųª ¹«½ÃÇÒ ¼ö ¾ø´Ù. - ±âº» ó¸® ¹æ¹ýÀº Áß´ÜµÈ ÇÁ·Î¼¼½º¸¦ Àç½ÃÀÛÇÏ´Â °ÍÀÌ´Ù. ±×·¯³ª ÇÁ·Î¼¼½º°¡ ½ÅÈ£¸¦ ¹ÞÁö ¾Ê´Â´Ù¸é ½ÅÈ£¸¦ ¹ö¸°´Ù. - vi ¿¡µðÅ͸¦ »ç¿ëÇÒ ¶§ . Control-Z ¸¦ ´­·¯ ¼öÇàÀ» Àá½Ã Á¤Áö½ÃŰ¸é ½©ÀÌ Å° ÀÔ·ÂÀ» ó¸®ÇÏ°Ô µÇ´Âµ¥ . À̶§ fg ¸í·ÉÀ» ½ÇÇà½ÃŰ¸é ½©Àº vi ¿¡°Ô SIGCONT ½Ã±×³ÎÀ» Àü´ÞÇϸç . vi´Â ÀÌ ½Ã±×³Î¿¡ ´ëÇÑ Ã³¸®·Î È­¸éÀ» ´Ù½Ã ±×¸®°í »ç¿ëÀÚ Å° ÀÔ·ÂÀ» ¹Þ´Â »óÅ·Πµ¹¾Æ°£´Ù. ¡Þ SIGSTOP - SIGTSTP°ú µ¿ÀÏÇϳª catch Çϰųª ¹«½ÃÇÒ ¼ö ¾ø´Ù. - ÀÌ ½ÅÈ£¸¦ ¹ÞÀ¸¸é ¹«Á¶°Ç SIGCONT ½ÅÈ£¸¦ ¹ÞÀ» ¶§±îÁö ÇÁ·Î¼¼½º¸¦ Áß´ÜÇÑ´Ù. ¡Þ SIGABRT - abort() ÇÔ¼öÀÇ È£Ãâ·Î ¹ß»ý ¡Þ SIGBUS - Çϵå¿þ¾î °áÇÔÀ¸·Î ¹ß»ý ¡Þ SIGEMT - Çϵå¿þ¾î °áÇÔÀ¸·Î ¹ß»ý ¡Þ SIGFPE - divide-by-0³ª ºÎµ¿ ¼Ò¼ýÁ¡ ¿À¹öÇ÷οì¿Í °°Àº »ê¼ú ¿¬»ê ¿À·ù¿¡¼­ ¹ß»ý ¡Þ SIGILL ¡Þ SIGINFO ¡Þ SIGIO ¡Þ SIGIOT ¡Þ SIGPIPE - pipe Åë½Å¿¡¼­ ¼ö½Å ÇÁ·Î¼¼½º°¡ Á¾·áÇßÀ» ¶§ ¼Û½Å ÇÁ·Î¼¼½º°¡ ÆÄÀÌÇÁ¿¡ write ÇÏ¸é ¹ß»ý - ÇÁ·Î¼¼½º°¡ RST¸¦ ¹ÞÀº ¼ÒÄÏ¿¡ µ¥ÀÌÅ͸¦ ¾²¸é, Ä¿³ÎÀº ±× ÇÁ·Î¼¼½º¿¡ ISGPIPE ½ÅÈ£¸¦ º¸³½´Ù. - ÀÌ ½ÅÈ£ÀÇ ±âº» µ¿ÀÛÀº ÇÁ·Î¼¼½º¸¦ Á¾·á½ÃŰ´Â °ÍÀ̹ǷÎ, ÇÁ·Î¼¼½º°¡ ¿øÇÏÁö ¾Ê´Â Á¾·á¸¦ ÇÇÇϱâ À§Çؼ­´Â ÀÌ ½ÅÈ£¸¦ Æ÷ÂøÇØ¾ß ÇÑ´Ù. ¡Þ SIGPOLL ¡Þ SIGROF ¡Þ SIGPWR ¡Þ SIGSYS ¡Þ SIGTTIN - background¿¡ ÀÖ´Â ÇÁ·Î¼¼½º°¡ Á¦¾î Å͹̳ηκÎÅÍÀÇ Àб⸦ ½ÃµµÇÑ´Ù. ¡Þ SIGTTOU - background¿¡ ÀÖ´Â ÇÁ·Î¼¼½º°¡ Á¦¾î Å͹̳ηκÎÅÍÀÇ ¾²±â¸¦ ½ÃµµÇÑ´Ù. ¡Þ SIGURG - SIGIO¿Í SIGURG ¶ó´Â µÎ °³ÀÇ ½ÅÈ£´Â ¼ÒÄÏÀÌ F_SETOWN ¸í·ÉÀ¸·Î ¼ÒÀ¯ÁÖ¿¡°Ô ÇÒ´çµÇ¾úÀ» ¶§¸¸ ¼ÒÄÏ¿¡ ´ëÇØ ¹ß»ýÇÑ´Ù. ¡Þ SIGUSR1 ¡Þ SIGUSR2 ¡Þ SIGVTALRM ¡Þ SIGWINCH ¡Þ SIGXCPU ¡Þ SIGXFSZ ¡á -- 2009-11-29 00:26:00 ¡á linux ¿¡¼­ÀÇ sigaction Á¤ÀÇ -- 2011-06-05 22:55:00 struct sigaction { union { __sighandler_t _sa_handler; void (*_sa_sigaction)(int, struct siginfo *, void *); } _u; sigset_t sa_mask ; unsigned long sa_flags; void (*sa_restorer)(void); }; #define sa_handler _u._sa_handler #define sa_sigaction _u._sa_sigaction ¡á solaris ¿¡¼­ÀÇ sigaction Á¤ÀÇ -- 2011-06-05 22:56:00 struct sigaction { int sa_flags; union { #ifdef __cplusplus void (*_handler)(int); #else void (*_handler)(); #endif #if defined(__EXTENSIONS__) || defined(_KERNEL) || \ (!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX)) || \ (_POSIX_C_SOURCE > 2) || defined(_XPG4_2) void (*_sigaction)(int, siginfo_t *, void *); #endif } _funcptr; sigset_t sa_mask; #ifndef _LP64 int sa_resv[2]; #endif }; #define sa_handler _funcptr._handler #define sa_sigaction _funcptr._sigaction ¡á freebsd ¿¡¼­ÀÇ sigaction Á¤ÀÇ -- 2011-06-05 22:59:00 struct sigaction { union { void (*__sa_handler)(int); void (*__sa_sigaction)(int, struct __siginfo *, void *); } __sigaction_u; // signal handler int sa_flags; // see signal options below sigset_t sa_mask; // signal mask to apply }; #define sa_handler __sigaction_u.__sa_handler /////////////////////////////////////////////////////////////////////////////*/ class ZCSigAction : public sigaction { public: typedef struct sigaction StSigAction; public: ZCSigAction() { ::memset((sigaction*)this, 0, sizeof(StSigAction)); }/* ZCSigAction()*/ StSigAction& GetBaseObj() { return (StSigAction&)(*this); }/* StSigAction& GetBaseObj()*/ void SetFlags(int AI_Flags) { this->sa_flags=AI_Flags; // RTS ¿¡´Â SA_SIGINFO ¸¦ ¼ÂÆÃ }/* void SetFlags(int AI_Flags)*/ void SetHandler(void (*APF_Handler)(int)) { this->sa_handler=APF_Handler; }/* void SetHandler(void (*APF_Handler)(int))*/ void SetHandlerEx(void (*APF_Handler)(int, siginfo_t*, void*)) { this->sa_sigaction=APF_Handler; // ÁÖ·Î RTS ¿¡¼­ »ç¿ëµÊ }/* void SetHandlerEx(void (*APF_Handler)(int, siginfo_t*, void*))*/ bool EmptySet() { return sigemptyset(&this->sa_mask)==0 ; }/* bool EmptySet()*/ bool FillSet() { return sigfillset(&this->sa_mask)==0 ; }/* bool FillSet()*/ bool CutSet(int AI_SigNo) { return sigdelset(&this->sa_mask, AI_SigNo)==0 ; }/* bool CutSet(int AI_SigNo)*/ bool AddSet(int AI_SigNo) { return sigaddset(&this->sa_mask, AI_SigNo)==0 ; }/* bool AddSet(int AI_SigNo)*/ bool Act(int AI_SigNum, struct sigaction* AP_OldSigAction=0) { return ::sigaction(AI_SigNum, this, AP_OldSigAction)==0 ; }/* bool Act(int AI_SigNum, struct sigaction* AP_OldSigAction=0)*/ static ZTypUInt Alarm(ZTypUInt AI_Sec) { return ::alarm(AI_Sec); /* AI_Sec 0 Àº ³ª¸ÓÁö ¾Ë¶÷ ¿äûÀ» Ãë¼Ò. ³ª¸ÓÁö ¾Ë¶÷ È£Ãâ ÀÌ Àü´ÞµÇ±â Àü¿¡ ³²¾ÆÀÖ´Â ½Ã°£À» ¹ÝȯÇϰųª È£ÃâÀÌ ½ÇÆÐÇϸé -1 À» ¹ÝȯÇÑ´Ù. */ }/* static ZTypUInt Alarm(ZTypUInt AI_Sec)*/ static bool Kill(int AI_SigNo, pid_t AI_Pid=::getpid()) { return ::kill(AI_Pid, AI_SigNo)==0 ; }/* static bool Kill(int AI_SigNo, pid_t AI_Pid=::getpid())*/ #ifdef __linux__ /*///////////////////////////////////////////////////////////////////////// ¡á freebsd 8.2, solaris 5.11 ¿¡¼­´Â F_SETSIG ÀÌ Á¤Àǰ¡ µÇ¾î ÀÖÁö ¾Ê¾Æ¼­, ¾Æ·¡ SetupRTS() ÇÔ¼ö¸¦ »ç¿ëÇÒ ¼ö ¾ø´Ù. Áï RTS ¿Í ¼ÒÄÏÀ» ¿¬µ¿ÇÒ ¼ö ¾ø´Ù. -- 2011-06-09 04:25:00 /////////////////////////////////////////////////////////////////////////*/ // ÁÖ·Î SIGRTMIN ~ SIGRTMAX »çÀÌ¿¡ ÀÖ´Â RTS ¸¦ ¼³Á¤ÇÑ´Ù. static bool SetupRTS(int AI_FileID, int AI_SigNo=SIGRTMIN, int AI_Flag=O_RDWR | /*O_NONBLOCK|*/O_ASYNC, pid_t AI_PId=::getpid()) { if (::fcntl(AI_FileID, F_SETFL, AI_Flag) < 0) { return false; } if (::fcntl(AI_FileID, F_SETSIG, AI_SigNo) < 0) { return false; } if (::fcntl(AI_FileID, F_SETOWN, AI_PId) < 0) { return false; }/* if (::fcntl(AI_FileID, F_SETOWN, AI_PId) < 0)*/ return true; }/* static bool SetupRTS(int AI_FileID, int AI_SigNo=SIGRTMIN, int AI_Flag=O_RDWR | O_NONBLOCK| O_ASYNC, int pid_t=::getpid())*/ #endif //__linux__ public: };/* class ZCSigAction*/ class ZCSigSet { private: ::sigset_t mi_SigSet; public : ::sigset_t& GetSigSet() { return mi_SigSet; }/* ::sigset_t& GetSigSet()*/ bool Empty() { return ::sigemptyset(&mi_SigSet)==0; }/* bool Empty()*/ bool Fill() { return ::sigfillset(&mi_SigSet)==0; }/* bool Fill()*/ bool Add(int AI_SigNo) { return ::sigaddset(&mi_SigSet, AI_SigNo)==0; }/* bool Add(int AI_SigNo)*/ bool Cut(int AI_SigNo) { return ::sigdelset(&mi_SigSet, AI_SigNo)==0; }/* bool Cut(int AI_SigNo)*/ bool IsMember(int AI_SigNo) { return ::sigismember(&mi_SigSet, AI_SigNo)==1; }/* bool IsMember(int AI_SigNo)*/ bool ProcMask(int AI_How, sigset_t* AP_OldSigSet=0) { return ::sigprocmask(AI_How, &mi_SigSet, AP_OldSigSet)==0; }/* bool ProcMask(int AI_How, sigset_t* AP_OldSigSet=0)*/ /*////////////////////////////////////////////////////////////// ¡á int AI_How °¡ °¡Áú ¼ö ÀÖ´Â °ª. SIG_BLOCK The set of blocked signals is the union of the current set and the set argument. ÁöÁ¤µÈ ½Ã±×³Î ¸¶½ºÅ©¸¦ ÇöÀç ½Ã±×³Î ºí·Ï ¸¶½ºÅ©¿¡ Ãß°¡ÇÑ´Ù. ºí·ÏµÈ ½Ã±×³ÎÀº ÇØ´ç ½Ã±×³ÎÀÌ ¹ß»ýÇßÀ»¶§, ÁöÁ¤µÈ ½Ã±×³Î ÇÚ µé·¯°¡ ½ÇÇàÀ» ¿Ï·áÇÒ ¶§±îÁö ºí·°µÈ´Ù. ºí·ÏµÇÁö ¾ÊÀº ½Ã±×³ÎÀ̶ó¸é, ÇØ´ç ½Ã±×³ÎÀÌ ¹ß»ýÇßÀ»¶§, ÁöÁ¤ µÈ ½Ã±×³Î Çڵ鷯¸¦ ¼öÇàÇÏ´Ù°¡, ´Ù¸¥ ½Ã±×³ÎÀÌ ¹ß»ýÇϸé, ½ÇÇà À» ÁßÁöÇϰí, ±× ½Ã±×³ÎÀÇ Çڵ鷯ÀÇ ½ÇÇàÀÌ ³¡³­ ÈÄ¿¡, ÁßÁöµÈ ÁöÁ¡ºÎÅÍ Àç½ÃÀÛÇÏ°Ô µÈ´Ù. SIG_UNBLOCK The signals in set are removed from the current set of blocked signals. It is legal to attempt to unblock a signal which is not blocked. ÁöÁ¤µÈ ½Ã±×³Î ¸¶½ºÅ©¸¦ ÇöÀç ½Ã±×³Î ºí·Ï ¸¶½ºÅ©¿¡¼­ Á¦°ÅÇÑ´Ù. SIG_SETMASK The set of blocked signals is set to the argument set. -- 2011-06-09 21:37:00 //////////////////////////////////////////////////////////////*/ bool Wait(int& ARRI_SigNo) { return ::sigwait(&mi_SigSet, &ARRI_SigNo)==0; }/* bool Wait(int& ARRI_SigNo)*/ int WaitInfo(siginfo_t& ARR_StSigInfo) { return ::sigwaitinfo(&mi_SigSet, &ARR_StSigInfo); }/* int WaitInfo(siginfo_t& ARR_StSigInfo)*/ /*////////////////////////////////////////////////////////////////// ¡á SYNOPSIS #include int sigwaitinfo(const sigset_t *restrict set, siginfo_t *restrict info); int sigtimedwait( const sigset_t *restrict set , siginfo_t *restrict info, const struct timespec *restrict timeout); ¡á RETURN VALUES Upon successful completion (that is, one of the signals specified by set is pending or is generated) sigwaitinfo() and sigtimedwait() will return the selected signal number. Otherwise, the function returns -1 and sets errno to indi- cate the error. ¡á ERRORS The sigwaitinfo() and sigtimedwait() functions will fail if: EINTR The wait was interrupted by an unblocked, caught signal. ENOSYS The sigwaitinfo() and sigtimedwait() functions are not supported. The sigtimedwait() function will fail if: EAGAIN No signal specified by set was generated within the specified timeout period. The sigwaitinfo() and sigtimedwait() functions may fail if: EFAULT The set, info, or timeout argument points to an invalid address. The sigtimedwait() function may fail if: EINVAL The timeout argument specified a tv_nsec value less than zero or greater than or equal to 1000 million. The system only checks for this error if no signal is pending in set and it is necessary to wait. ¡á -- 2011-06-02 01:14:00 //////////////////////////////////////////////////////////////////*/ static bool AddInfo(int AI_SignalNo, const union sigval AI_SigVal, int AI_ProcessID=::getpid()) { return ::sigqueue(AI_ProcessID, AI_SignalNo, AI_SigVal)==0; }/* static bool AddInfo(int AI_SignalNo, const union sigval AI_SigVal, int AI_ProcessID=::getpid())*/ /*////////////////////////////////////////////////////////////////// ¡á SYNOPSIS #include #include union sigval{int sival_int; void* sival_ptr;}; int sigqueue(pid_t pid, int signo, const union sigval value); ¡á RETURN VALUES Upon successful completion, the specified signal will have been queued, and the sigqueue() function returns 0. Other- wise, the function returns -1 and sets errno to indicate the error. ¡á ERRORS The sigqueue() function will fail if: EAGAIN No resources are available to queue the signal. The process has already queued SIGQUEUE_MAX sig- nals that are still pending at the receiver(s), or a system wide resource limit has been exceeded. EINVAL The value of signo is an invalid or unsupported signal number. ENOSYS The sigqueue() function is not supported by the system. EPERM The process does not have the appropriate privilege to send the signal to the receiving process. ESRCH The process pid does not exist. ¡á -- 2011-06-02 01:40:00 //////////////////////////////////////////////////////////////////*/ public: };/* class ZCSigSet*/ class ZCProcess { public: // cf) typedef int pid_t // µ¥¸óÀ» ¸¸µå´Â ¿ëµµ·Îµµ °¡´ÉÇÑ ÇÔ¼öÀÌ´Ù. bool Exec(const char* AP_ExeName, bool AB_DoCloseStdInOut=true) { return this->Exec(AP_ExeName, NULL, AB_DoCloseStdInOut); }/* bool Exec(const char* AP_ExeName, bool AB_DoCloseStdInOut=true)*/ bool Exec(const char* AP_ExeName, char* const APA_Arg[], bool AB_DoCloseStdInOut=true) { /*///////////////////////////////////////////////////////////////// ¡á APA_Arg ÀÇ ¸¶Áö¸· ¿ø¼Ò´Â NULL ·Î ³¡³ª¾ß ÇÑ´Ù. char *aRgu[4]; aRgu[0] = "/test/test.exe"; aRgu[1] = "ABC"; // Argu 1 aRgu[2] = "10" ; // Argu 2 aRgu[3] = 0 ; // ¾Æ±Ô¸ÕÆ®°¡ ³¡À̶ó´Â °Í¸¦ ²À ÁöÁ¤ÇÏ¿©¾ß ÇÑ´Ù. execvp(aRgu[0] , aRgu); ¡á execl »ç¿ë·Ê ::execl( "./WinSEC_D.exe" , "./WinSEC_D.exe" , "WinSEC_Conf.txt", NULL ////// ); /////////////////////////////////////////////////////////////////*/ if(AP_ExeName==0 || AP_ExeName[0]==0) return false; int VI_ForkNum = ::fork(); /*####################*/ if(VI_ForkNum==0) // child { if(AB_DoCloseStdInOut==true) { ::close(0); ::close(1); }/* if(AB_DoCloseStdInOut==true)*/ ::setsid(); // ÀÚ±â ÀÚ½ÅÀ» ¼¼¼ÇÀÇ ¸®´õ·Î ¸¸µç´Ù. ::execvp(AP_ExeName, APA_Arg); return true; } else if(VI_ForkNum==-1) // error { return false; } else // ºÎ¸ðÀÇ °æ¿ì { return true; }/* else*/ }/* bool Exec(const char* AP_ExeName, char* const APA_Arg[], bool AB_DoCloseStdInOut=true)*/ static pid_t Fork (){return ::fork ();} static int GetPPID(){return ::getppid();} static int GetUID (){return ::getuid ();} static int GetGID (){return ::getgid ();} static long GetPID (){return ::getpid ();} public: };/* class ZCProcess*/ class ZCMemMap { public: static void* LinkMap( int AI_FileDesc, off_t AL_Offset=0, size_t AL_MapSize=0, int AI_Protect=PROT_READ | PROT_WRITE, int AI_Flags=MAP_SHARED, void* AP_BaseAddress=NULL) { return ::mmap(AP_BaseAddress, AL_MapSize, AI_Protect, AI_Flags, AI_FileDesc, AL_Offset); }/* static void* LinkMap( int AI_FileDesc, off_t AL_Offset=0, size_t AL_MapSize=0, int AI_Protect=PROT_READ | PROT_WRITE, int AI_Flags=MAP_SHARED, void* AP_BaseAddress=NULL) */ /* munmap(void*,size_t) Upon successful completion, munmap() returns 0. Otherwise, it returns -1 and sets errno to indicate the error */ static bool UnMap(void* AP_BaseAddress, size_t AL_Size) { return ::munmap(AP_BaseAddress, AL_Size)==0; }/* static bool UnMap(void* AP_BaseAddress, size_t AL_Size)*/ public: };/* class ZCMemMap*/ /*///////////////////////////////////////////////////////////////////////////// SHMGET(2) ¸®´ª½º ÇÁ·Î±×·¡¸Ó ¸Þ´º¾ó SHMGET(2) ¡á À̸§ shmget - °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®¸¦ ÇÒ´çÇÑ´Ù. ¡á »ç¿ë¹ý #include #include int shmget(key_t key, int size, int shmflg); ¡á ¼³¸í shmget() ´Â key ÀÎÀÚ°ª°ú °ü·ÃµÈ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ® ½Äº°ÀÚ¸¦ ¹ÝȯÇÑ´Ù. ¸¸ÀÏ, key °¡ IPC_PRIVATE °ªÀ» °¡Áö°í Àְųª ¶Ç´Â key °¡ IPC_PRIVATE °¡ ¾Æ ´Ï°í, key ¿Í ¿¬°èµÇ¾î ÀÖ´Â °øÀ¯¸Þ¸ð¸® ¼¼±×¸ÕÆ®°¡ ¾ø´Ù¸é PAGE_SIZE ÀÇ ¹è¼ö¸¸Å­ÀÇ size ¸¦ °¡Áö°í ÀÖ´Â »õ·Î¿î °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®°¡ ¸¸µé ¾î Áø ´Ù. IPC_CREAT ´Â shmflg ¿¡ ¸í½ÃµÇ¾î ÀÖ´Ù. (i.e. shmflg&IPC_CREAT ´Â 0ÀÌ ¾Æ´Ï´Ù.) shmflg ÀÇ ±¸¼ºÀº ´ÙÀ½°ú °°´Ù: IPC_CREAT »õ·Î¿î ¼¼±×¸ÕÆ®¸¦ ¸¸µç´Ù. ¸¸ÀÏ ÀÌ Ç÷¡±×°¡ »ç¿ëµÇÁö ¾Ê´Â ´Ù ¸é, shmget() ´Â key¿Í °ü·ÃµÈ ¼¼±×¸ÕÆ®¸¦ ãÀ» °ÍÀ̸ç, »ç¿ëÀÚ °¡ ±× ¼¼±×¸ÕÆ®¿Í °ü·ÃµÈ shmid ¸¦ ¹ÞÀ» Çã°¡±ÇÀÌ ÀÖ´ÂÁö ¾Ë ±â À§Çؼ­ °Ë»çÇÑ´Ù. ±×¸®°í ¼¼±×¸ÕÆ®°¡ ÆÄ±«µÇ¾ú´Ù´Â Ç¥½Ã¸¦ ÇÏÁö ¾Êµµ·Ï º¸ÀåÇÑ´Ù. IPC_EXCL ¼¼±×¸ÕÆ®°¡ Á¸ÀçÇÒ°æ¿ì ½ÇÆÐ¸¦ º¸ÀåÇϱâ À§ÇØ IPC_CREAT¿Í ÇÔ²² »ç¿ëµÈ´Ù. mode_flags (lowest 9 bits) ¼Ò À¯ ÀÚ, ±×·ì, ±× ¿ÜµéÀ» º¸ÀåÇϱâ À§ÇØ Çã°¡±ÇÀ» ÁöÁ¤ÇÑ´Ù. ÇöÀç, ½ÇÇà Çã°¡±ÇÀº ½Ã½ºÅÛ¿¡ ÀÇÇØ »ç¿ëµÇÁö ¾Ê´Â´Ù. »õ·Î¿î ¼¼±×¸ÕÆ®°¡ »ý¼ºµÈ´Ù¸é, shmflg ÀÇ Á¢±Ù Çã°¡±ÇÀº¼¼±×¸ÕÆ®¿¡ Á¤ÀÇ µÇ ¾î ÀÖ´Â shmid_ds ÀÇ shm_perm ¸â¹ö·Î º¹»çµÈ´Ù. shmid_ds ±¸Á¶Ã¼: struct shmid_ds { struct ipc_perm shm_perm; // ÆÛ¹Ì¼Ç int shm_segsz; // ¼¼±×¸ÕÆ®ÀÇ Å©±â(bytes) time_t shm_atime; // ¸¶Áö¸· Á¢±Ù ½Ã°£ time_t shm_dtime; // ¸¶Áö¸· Á¦°Å ½Ã°£ time_t shm_ctime; // ¸¶Áö¸· º¯°æ ½Ã°£ unsigned short shm_cpid; // »ý¼ºÀÚÀÇ pid unsigned short shm_lpid; // ¸¶Áö¸·À¸·Î ÀÛµ¿ÇÑ ÇÁ·Î¼¼½º pid short shm_nattch; // ÇöÀç Á¢±ÙÇÑ ÇÁ·Î¼¼½ºÀÇ ¼ö }; struct ipc_perm { key_t key; ushort uid; // ¼ÒÀ¯ÀÚÀÇ euid ¿Í egid ushort gid; ushort cuid; // »ý¼ºÀÚÀÇ euid ¿Í egid ushort cgid; ushort mode; // shmflgÀÇ ÇÏÀ§ 9ºñÆ® ushort seq; // ¿¬¼Ó ¼ö(sequence number) }; °Ô´Ù°¡, »ý¼ºµÇ´Â µ¿¾È ½Ã½ºÅÛ ÄÝÀº ½Ã½ºÅÛ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ® µ¥ÀÌÅÍ ±¸ Á¶ shmid_ds ¸¦ ´ÙÀ½°ú °°ÀÌ ÃʱâÈ­ÇÑ´Ù. shm_perm.cuid ¿Í shm_perm.uid ´Â È£Ãâ ÇÁ·Î¼¼½ºÀÇ À¯È¿ user-ID ·Î ¼³Á¤µÈ´Ù. shm_perm.cgid ¿Í shm_perm.gid ´Â È£Ãâ ÇÁ·Î¼¼½ºÀÇ À¯È¿ group-ID·Î ¼³Á¤µÈ´Ù. shm_perm.mode ÀÇ ÇÏÀ§ 9ºñÆ®µéÀº shmflg ÀÇ ÇÏÀ§ 9ºñÆ®µé·Î ¼³Á¤ µÈ ´Ù. shm_segsz ´Â size °ªÀ¸·Î ¼³Á¤µÈ´Ù. shm_lpid, shm_nattch, shm_atime ±×¸®°í shm_dtime ´Â 0 À¸·Î ¼³Á¤ µÈ´Ù. shm_ctime ´Â ÇöÀç ½Ã°£À¸·Î ¼³Á¤µÈ´Ù. ¸¸ÀÏ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®°¡ ÀÌ¹Ì Á¸ÀçÇÑ´Ù¸é, Á¢±Ù Çã°¡±ÇÀÌ Á¶»çµÇ¸ç, ÆÄ ±«µµµµ·Ï Ç¥½ÃµÇ¾î ÀÖ´ÂÁö ¾Ë¾Æº¸±â À§ÇØ °Ë»çÇÑ´Ù. ¡á SYSTEM CALLS fork() fork() ÈÄ¿¡ ÀÚ½Ä ÇÁ·Î¼¼½º´Â ¿¬°áµÈ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®µéÀ» »ó¼Ó ÇÑ´Ù. exec() exec() ÈÄ¿¡ ¿¬°áµÈ ¸ðµç °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®´Â ºÐ¸®µÈ´Ù.(ÆÄ±« µÇ ´Â°ÍÀÌ ¾Æ´Ï´Ù) exit() exit() ½Ã ¿¬°áµÈ ¸ðµç °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®´Â ºÐ¸®µÈ´Ù.(ÆÄ±«µÇ´Â °ÍÀÌ ¾Æ´Ï´Ù) ¡á ¹Ýȯ°ª ¼º°ø½Ã À¯È¿ÇÑ ¼¼±×¸ÕÆ® ½Äº°ÀÚ shmid °¡ ¹ÝȯµÇ¸ç, ¿¡·¯½Ã -1ÀÌ ¹ÝȯµÈ ´Ù. ¡á ¿¡·¯ ½ÇÆÐ½Ã, errno ´Â ´ÙÀ½Áß Çϳª·Î ¼³Á¤µÈ´Ù: EINVAL ¸¸ÀÏ SHMMIN > size, ¶Ç´Â size > SHMMAX, ¶Ç´Â sizeÀÌ ¼¼±×¸Õ Æ®ÀÇ Å©±âº¸´Ù Å©´Ù¸é ÀÌ¿¡·¯°¡ ¹ÝȯµÈ´Ù. EEXIST IPC_CREAT | IPC_EXCL ÀÌ ÁöÁ¤µÇ¾î ÀÖ°í, ¼¼±×¸ÕÆ®°¡ Á¸ÀçÇÏ ¸é ÀÌ ¿¡·¯°¡ ¹ÝȯµÈ´Ù. EIDRM ¼¼±×¸ÕÆ®°¡ ÆÄ±«³ª Á¦°ÅµÇµµ·Ï Ç¥½ÃµÇ¾î ÀÖ´Ù¸é ÀÌ ¿¡·¯°¡ ¹ÝȯµÈ´Ù. ENOSPC °¡´ÉÇÑ ¸ðµç °øÀ¯ ¸Þ¸ð¸® id (SHMMNI) ¸¦ °¡Á³°Å³ª ¿äûµÈ size ÀÇ ¼¼±×¸ÕÆ® ÇÒ´çÀÌ ½Ã½ºÅÛ Àüü °øÀ¯ ¸Þ¸ð¸® Á¦ÇѰª (SHMALL) À» ÃʰúÇÒ°æ¿ì ¹ÝȯµÈ´Ù. ENOENT ÁÖ¾îÁø key¿¡ ÇØ´çÇÏ´Â ¼¼±×¸ÕÆ®°¡ Á¸ÀçÇÏÁö ¾Ê°í, IPC_CREAT °¡ ÁöÁ¤µÇÁö ¾Ê¾Ò´Ù¸é ¹ÝȯµÈ´Ù. EACCES »ç¿ëÀÚ°¡ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®¿¡ ´ëÇÑ Á¢±Ù Çã°¡±ÇÀÌ ¾øÀ»¶§ ¹ÝȯµÈ´Ù. ENOMEM ¼¼±×¸ÕÆ®¸¦ À§ÇØ ÇÒ´çÇÒ ¸Þ¸ð¸®°¡ ¾øÀ»¶§ ¹ÝȯµÈ´Ù. ¡Ø ÁÖÀÇ IPC_PRIVATE ´Â Ç÷¹±× Çʵ尡 ¾Æ´Ï¶ó key_t ŸÀÔÀÌ´Ù. ÀÌ Æ¯º°ÇÑ °ªÀÌ key¿¡ »ç¿ëµÈ´Ù¸é, ½Ã½ºÅÛ ÄÝÀº shmflg ÀÇ ÇÏÀ§ 9ºñÆ®µé¿Ü ¸ðµç°ÍÀ» ¹«½ÃÇÑ´Ù. ±×¸®°í »õ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®¸¦ »ý¼º(¼º°ø½Ã)ÇÑ´Ù. ´ÙÀ½Àº shmget ½Ã½ºÅÛ ÄÝ¿¡ ¿µÇâÀ» ÁÖ´Â °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ® ÀÚ¿øµéÀÇ Á¦ÇѰªµéÀÌ´Ù: SHMALL ½Ã½ºÅÛ ÀüüÀÇ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ® ÃÖ´ë °ª: Á¤Ã¥ ÀÇÁ¸ÀûÀÌ´Ù. SHMMAX °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®ÀÇ ÃÖ´ë Å©±â(¹ÙÀÌÆ®¼ö): ¼öÇà ÀÇÁ¸ÀûÀÌ´Ù.(ÇöÀç 4M) SHMMIN °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®ÀÇ ÃÖ¼Ò Å©±â(¹ÙÀÌÆ®¼ö): ¼öÇà ÀÇÁ¸ÀûÀÌ´Ù. (PAGE_SIZE °¡ À¯È¿ÇÑ ÃÖ¼Ò Å©±âÀÌÁö¸¸, ÇöÀç´Â 1byteÀÌ´Ù.) SHMMNI ½Ã½ºÅÛ ÀüüÀÇ °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ® ÃÖ´ë ¼ö: ¼öÇà ÀÇÁ¸ÀûÀÌ´Ù(ÇöÀç 4096) ¼öÇà½Ã ÇÁ·Î¼¼½º´ç °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®ÀÇ Æ¯º°ÇÑ Á¦ÇÑÀº ¾ø´Ù. (SHMSEG) /////////////////////////////////////////////////////////////////////////////*/ // °øÀ¯¸Þ¸ð¸® Ŭ·¡½º class ZCShareMemory { private: enum{EInvalidID=-1}; private: ZTypeID mh_FileMap; void* mp_Address; public : ZCShareMemory() { mh_FileMap= EInvalidID; mp_Address= 0 ; }/* ZCShareMemory()*/ ZTypeID GetID() const { return mh_FileMap; }/* ZTypeID GetID() const*/ bool IsValidID() const { return mh_FileMap != -1; }/* bool IsValidID() const*/ void* GetStartAddress() const { return mp_Address; }/* void* GetStartAddress() const*/ bool Create(const char* AP_MapName, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return Create((key_t)(ZNsMain::ZfGetKeyNum(AP_MapName)), AL_MapSize, AI_Flag); }/* bool Create(const char* AP_MapName, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool Create(long AL_MapID, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { if((mh_FileMap=::shmget((key_t)AL_MapID, AL_MapSize, AI_Flag))==-1) { if(errno==EEXIST) { return (mh_FileMap=::shmget(AL_MapID, 0, 0)) != -1; }/* if(errno==EEXIST)*/ return false; }/* if((mh_FileMap=::shmget((key_t)AL_MapID, AL_MapSize, AI_Flag))==-1)*/ return true; }/* bool Create(long AL_MapID, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool ShmGet(const char* AP_MapName, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return (mh_FileMap=::shmget((key_t)(ZNsMain::ZfGetKeyNum(AP_MapName)), AL_MapSize, AI_Flag))!=-1 ; }/* bool ShmGet(const char* AP_MapName, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool ShmGet(const char* AP_MapName) { return (mh_FileMap=::shmget((key_t)(ZNsMain::ZfGetKeyNum(AP_MapName)), 0 ,0))!=-1 ; }/* bool ShmGet(const char* AP_MapName)*/ bool ShmGet(long AL_MapID, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return (mh_FileMap=::shmget((key_t)AL_MapID, AL_MapSize, AI_Flag))!=-1 ; }/* bool ShmGet(long AL_MapID, long AL_MapSize, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool ShmGet(long AL_MapID) { // key °¡ AL_MapID ÀÎ °øÀ¯¸Þ¸ð¸®°¡ ÀÖ´ÂÁö Á¶»ç return (mh_FileMap=::shmget((key_t)AL_MapID, 0, 0))!=-1 ; }/* bool ShmGet(long AL_MapID)*/ bool LinkMap() { // void *shmat(int shmid, const void *shmaddr, int shmflg); return (mp_Address=::shmat(mh_FileMap, (void*)0, 0))!=NULL ; // shmat() ÀÇ 3 ¹øÂ° Àμö·Î SHM_RDONLY Ç÷¡±×¸¦ ÁöÁ¤Çϸé // °øÀ¯ ¸Þ¸ð¸® ¼¼±×¸ÕÆ®´Â ¸ÅÇεǾîÁöÁö¸¸, ÀбâÀü¿ë(readonly)·Î Ç¥½ÃµÈ´Ù }/* bool LinkMap()*/ bool UnMap() { // cf) In Window : BOOL UnmapViewOfFile(LPCVOID lpBaseAddress); bool VB_IsOK=(::shmdt(mp_Address)!=-1); mp_Address=0; return VB_IsOK; }/* bool UnMap()*/ bool Close() { bool VB_IsOK=(::shmctl(mh_FileMap, IPC_RMID, 0)!=-1) ; mh_FileMap=EInvalidID; return VB_IsOK; /* IPC_RMID ¸í·É¾î´Â ½ÇÁ¦·Î Ä¿³Î·Î ºÎÅÍ ¼¼±×¸ÕÆ®¸¦ Á¦°ÅÇÏ´Â °ÍÀº ¾Æ´Ï´Ù. Á¦°ÅÇϱâ À§ÇØ ¼¼±×¸ÕÆ®¿¡ Ç¥½Ã¸¦ ÇØµÐ´Ù. ½ÇÁ¦ÀûÀÎ Á¦°Å ÀÚü´Â ÇöÀç ¼¼±×¸ÕÆ®¿¡ ºÙ¾î ÀÖ´Â(attached) ¸¶Áö¸· ÇÁ·Î¼¼½º°¡ ÀûÀýÈ÷ ºÐ¸®µÆÀ»(detached) ¶§ ÀϾ´Ù. ¹°·Ð, ÇöÀç ¼¼±×¸ÕÆ®¿¡ ºÙ¾îÀÖ´Â (attached) ÇÁ·Î¼¼½º°¡ ¾øÀ¸¸é, Á¦°Å´Â Áï½Ã ÀÌ·ç¾î Áø´Ù. */ }/* bool Close()*/ public: };/* class ZCShareMemory*/ /*//////////////////////////////////////////////////////////////////////////////////////// ¡á class ZCProcessMutex ´Â ÇÁ·Î¼¼½ºÀÇ ¹ÂÅØ½º. Window ¿¡¼­´Â À̸§ÀÖ´Â mutex ¸¦ ¾²¸é °£´ÜÇÏÁö¸¸, Linux ¿¡¼­´Â ¼¼¸¶Æ÷¾î¸¦ ¾µ ¼öµµ ÀÖ´Ù. pthread ¶óÀ̺귯¸®¸¦ ½á¼­ °øÀ¯¸Þ¸ð¸®¿¡ mutex µ¥ÀÌŸ¸¦ ³Ö¾îµµ µÇÁö¸¸ ±×¸¸Å­ ÀܼÕÁúÀÌ ÇÊ¿äÇÏ´Ù. Linux ¿¡¼­´Â ´ÙÁß¾²·¹µå¿¡¼­ ¾²´Â ¼¼¸¶Æ÷¾î¿Í ´ÙÁß ÇÁ·Î¼¼½º¿¡¼­ ¾²´Â ¼¼¸¶Æ÷¾î°¡ ´Ù¸£´Ù. Á¤È®È÷´Â pthread °¡ ÇÁ·Î¼¼½º ¼¼¸¶Æ÷¾î¸¦ ¾ÆÁ÷ Áö¿øÇÏÁö ¾Ê´Â´Ù. (2006-12-28 16:02:00) ////////////////////////////////////////////////////////////////////////////////////////*/ class ZCProcessMutex { private: ZTypeID mh_Mutex; private: bool Init(int AI_InitNum=1) { // ¸®´ª½º¿¡¼­¸¸ °¡´É // ¼¼¸¶Æ÷¾îÀÇ °ªÀ» ÃʱâÈ­ÇÑ´Ù. union semun SemUnion; SemUnion.val=AI_InitNum; return ::semctl(mh_Mutex, 0, SETVAL, SemUnion)!=-1 ; /*////////////////////////////////////////////////////////// int semctl(int semid, int semnum, int cmd, ...) If successful, the value returned by semctl() depends on cmd as follows: GETVAL The value of semval. GETPID The value of sempid. GETNCNT The value of semncnt. GETZCNT The value of semzcnt. All others 0. Otherwise, semctl() returns -1 and errno indicates the error //////////////////////////////////////////////////////////*/ }/* bool Init(int AI_InitNum=1)*/ /*private:*/ public : ZCProcessMutex() { mh_Mutex=0; }/* ZCProcessMutex()*/ ZTypeID GetHandle() const { return mh_Mutex; }/* ZTypeID GetHandle() const*/ // Linux ÀÇ °æ¿ì ÇÁ·Î¼¼½º ¼¼¸¶Æ÷¾î·Î Window ÀÇ ÇÁ·Î¼¼½º ¹ÂÅØ½º¸¦ ±¸ÇöÇÑ´Ù. // Window ÀÇ ¹ÂÅØ½º´Â ¾²·¹µå¿Í ÇÁ·Î¼¼½º¿¡ ¸ðµÎ »ç¿ëÇÒ ¼ö ÀÖÁö¸¸ Linux ÀÇ // °æ¿ì¿¡´Â ±×·¸Áö ¾Ê´Ù. 2006-08-06 15:55:00 bool Make(const char* AP_MutexName, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return this->Make(ZNsMain::ZfGetKeyNum(AP_MutexName), AI_Flag); }/* bool Make(const char* AP_MutexName, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool Make(long AL_KeyID, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { // AI_Flag ´Â IPC_CREAT,IPC_EXCL,0 ÀÇ ¼¼ °ªÁßÀÇ ÇϳªÀ̸ç // 0 À̸é ÇØ´ç µ¿±âÈ­object °¡ Á¸ÀçÇÒ ¶§¸¸ ¿¬´Ù. // int semget(key_t key,int nsems,int semflg) if((mh_Mutex=::semget((key_t)AL_KeyID, 1, AI_Flag))==-1) { if(errno==EEXIST) { return (mh_Mutex=::semget((key_t)AL_KeyID, 1, 0)) != -1; }/* if(errno==EEXIST)*/ return false; }/* if((mh_Mutex=::semget((key_t)AL_KeyID, 1, AI_Flag))==-1)*/ this->Init(); return true; }/* bool Make(long AL_KeyID, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool Lock() { struct sembuf sembuf_Obj; sembuf_Obj.sem_num= 0; // semaphore ¹è¿­¿¡¼­ ¸î ¹øÂ° semaphore ÀÎÁö¸¦ ÁöÁ¤ sembuf_Obj.sem_op =-1; sembuf_Obj.sem_flg=SEM_UNDO; return ::semop(mh_Mutex, &sembuf_Obj, 1)==0 ; }/* bool Lock()*/ bool UnLock() { struct sembuf sembuf_Obj; sembuf_Obj.sem_num=0 ; // semaphore ¹è¿­¿¡¼­ ¸î ¹øÂ° semaphore ÀÎÁö¸¦ ÁöÁ¤ sembuf_Obj.sem_op =1 ; sembuf_Obj.sem_flg=SEM_UNDO; return ::semop(mh_Mutex,&sembuf_Obj, 1)==0 ; }/* bool UnLock()*/ bool Close() { // Ä¿³Î¿¡¼­ semaphore °¡ Á¦°ÅµÈ´Ù. ÀÌ ÇÔ¼ö ¼öÇàÈÄ¿¡ ipcs ÇØ º¸¸é // semaphore ¸ñ·Ï¿¡ ³ªÅ¸³ªÁö ¾Ê´Â´Ù. µû¶ó¼­ ÀÌ ÇÔ ¼öÇà ÈÄ¿¡´Â Lock() // ¿¡¼­ ´ë±âÇϰí ÀÖ´ø ÇÁ·Î¼¼½º³ª ¾²·¹µå´Â ÇѲ¨¹ø¿¡ ±ú¾î³ª°í ´õÀÌ»ó // µ¿±âÈ­µÇÁö ¾Ê´Â´Ù. ÇÁ·Î¼¼½º°¡ ÀÌ ÇÔ¼ö¸¦ ¼öÇàÇÏÁö ¾Ê°í Á¾·áÇØµµ Ä¿ // ³ÎÀº ÀÚµ¿ÀûÀ¸·Î semaphore ¸¦ »èÁ¦ÇÏÁö ¾Ê´Â´Ù. union semun SemUnion; const bool CB_IsOK = (::semctl(mh_Mutex, 0, IPC_RMID, SemUnion)!=-1); mh_Mutex=0; return CB_IsOK; }/* bool Close()*/ public: };/* class ZCProcessMutex*/ /////////////////////////////////////////////// /////////// end class ZCProcessMutex /////////// /////////////////////////////////////////////// // posix mutex ·Î ÇÁ·Î¼¼½º°£ µ¿±âÈ­¸¦ Çϴ Ŭ·¡½º class ZCProcessMutexPosix { private: class ZCMutexData { protected: friend class ZCProcessMutexPosix; protected: pthread_mutex_t mo_PThreadMutex ; pthread_mutexattr_t mo_PThreadMutexAttr; protected: };/* class ZCMutexData*/ private: ZCMutexData* mp_MutexData ; ZCShareMemory mo_CShareMemory; public : ZCProcessMutexPosix() { mp_MutexData=0; }/* ZCProcessMutexPosix()*/ bool Make(LPCTSTR AP_MapName) { return Make( ZNsMain::ZfGetKeyNum(AP_MapName) ); }/* bool Make(LPCTSTR AP_MapName)*/ bool Make(long AL_MapKey) { if(mo_CShareMemory.ShmGet(AL_MapKey,sizeof(ZCMutexData))==false) { if(errno!=EEXIST || mo_CShareMemory.ShmGet(AL_MapKey)!=true) { return false; } if(mo_CShareMemory.LinkMap()==false) { mo_CShareMemory.Close(); return false; }/* if(mo_CShareMemory.LinkMap()==false)*/ mp_MutexData=(ZCMutexData*)mo_CShareMemory.GetStartAddress(); } else // mo_CShareMemory.ShmGet(AL_MapKey,sizeof(ZCMutexData))==true { if(mo_CShareMemory.LinkMap()==false) { mo_CShareMemory.Close(); return false; }/* if(mo_CShareMemory.LinkMap()==false)*/ mp_MutexData=(ZCMutexData*)mo_CShareMemory.GetStartAddress(); ::memset(mp_MutexData, 0x00, sizeof(ZCMutexData)); ::pthread_mutexattr_init (&mp_MutexData->mo_PThreadMutexAttr); ::pthread_mutexattr_settype (&mp_MutexData->mo_PThreadMutexAttr, PTHREAD_MUTEX_RECURSIVE); // ÀÌÀü¿¡´Â PTHREAD_MUTEX_ERRORCHECK ·Î ¼³Á¤Çß¾ú´Ù. 2007-05-24 20:04:00 ::pthread_mutexattr_setpshared(&mp_MutexData->mo_PThreadMutexAttr, PTHREAD_PROCESS_SHARED); ::pthread_mutex_init (&mp_MutexData->mo_PThreadMutex, (const pthread_mutexattr_t*)&mp_MutexData->mo_PThreadMutexAttr); }/* else // mo_CShareMemory.ShmGet(AL_MapKey,sizeof(ZCMutexData))==true*/ return true; }/* bool Make(long AL_MapKey)*/ bool Lock() { return this->LockRaw()==0; }/* int Lock()*/ int LockRaw() { return ::pthread_mutex_lock(&mp_MutexData->mo_PThreadMutex); // EDEADLK ¸¦ ¹ÝȯÇÏ´Â °æ¿ì¸¦ üũÇÒ °Í. }/* int Lock()*/ #ifdef __USE_XOPEN2K bool Lock(const struct timespec& AR_TimeSpec) { return this->LockRaw(AR_TimeSpec)==0; }/* int Lock(const struct timespec& AR_TimeSpec)*/ bool Lock(long AL_MiliSec) { return this->LockRaw(AL_MiliSec)==0; }/* int Lock(long AL_MiliSec)*/ int LockRaw(const struct timespec& AR_TimeSpec) { return ::pthread_mutex_timedlock(&mp_MutexData->mo_PThreadMutex, &AR_TimeSpec); // ¼º°øÀ̸é ZNsEnum::ZEThread_OK ¸¦ // ½Ã°£ÃʰúÀ̸é ZNsEnum::ZEThread_TimeOut ¸¦ ¸®ÅÏ // // EDEADLK ¸¦ ¹ÝȯÇÏ´Â °æ¿ì¸¦ üũÇÒ °Í. }/* int Lock(const struct timespec& AR_TimeSpec)*/ int LockRaw(long AL_MiliSec) { timespec VO_TimeSpec; VO_TimeSpec.tv_sec =time(NULL)+AL_MiliSec/1000; VO_TimeSpec.tv_nsec=(AL_MiliSec%1000)*1000*1000; return ::pthread_mutex_timedlock(&mp_MutexData->mo_PThreadMutex, &VO_TimeSpec); }/* int Lock(long AL_MiliSec)*/ int LockTime(long AL_MiliSec) { return LockRaw(AL_MiliSec); }/* int LockTime(long AL_MiliSec)*/ #endif // __USE_XOPEN2K bool UnLock() { return ::pthread_mutex_unlock(&mp_MutexData->mo_PThreadMutex)==0; }/* bool UnLock()*/ void Close() { ::pthread_mutex_destroy(&mp_MutexData->mo_PThreadMutex); mo_CShareMemory.UnMap(); mo_CShareMemory.Close(); }/* void Close()*/ public: };/* class ZCProcessMutexPosix*/ #ifdef __USE_XOPEN2K /*//////////////////////////////////////////////////////////////////////////////// ¡á ±â·ÏÀÚ/ÆÇµ¶ÀÚ lock(read-write lock) À¸·Î Window ÀÇ ¼öµ¿¸®¼Â À̺¥Æ®¸¦ ±¸ÇöÇÒ ¼ö ÀÖ´Ù. Áï Æ¯Á¤ ÁöÁ¡¿¡¼­ ´Ù¼öÀÇ ¾²·¹µå°¡ ´ë±âÇÏ´Ù°¡ µ¿½Ã¿¡ ±ú¾î³ª´Â µ¿ÀÛÀÌ °¡´ÉÇÏ ´Ù. ¹°·Ð ¹ÂÅØ½º Á¶°Çº¯¼ö·Î ¼öµ¿¸®¼Â À̺¥Æ®¸¦ ±¸ÇöÇÏ´Â °ÍÀÌ ´õ È¿°úÀûÀÌ´Ù. ¡á POSIX.1b structure for a time value. This is like a `struct timeval' but has nanoseconds instead of microseconds. struct timespec { __time_t tv_sec ; // Seconds. long int tv_nsec; // Nanoseconds. 10 ¾ïºÐÀÇ 1 ÃÊ, 1 ¹Ð¸®ÃÊ=1000*1000 ³ª³ëÃÊ }; ////////////////////////////////////////////////////////////////////////////////*/ class ZCLockRW_Base { protected: pthread_rwlock_t mo_pthread_rwlock_t; public: int Init() { return ::pthread_rwlock_init(&mo_pthread_rwlock_t, NULL); }/* int Init()*/ int LockRead() { return ::pthread_rwlock_rdlock(&mo_pthread_rwlock_t); }/* int LockRead()*/ int LockRead(const struct timespec& AR_TimeSpec) { return ::pthread_rwlock_timedrdlock(&mo_pthread_rwlock_t, &AR_TimeSpec); }/* int LockRead(const struct timespec& AR_TimeSpec)*/ int LockRead(long AL_MiliSec) { timespec VO_TimeSpec; VO_TimeSpec.tv_sec =time(NULL)+AL_MiliSec/1000; VO_TimeSpec.tv_nsec=(AL_MiliSec%1000)*1000*1000; return ::pthread_rwlock_timedrdlock(&mo_pthread_rwlock_t, &VO_TimeSpec); }/* int LockRead(long AL_MiliSec)*/ int TryLockRead() { return ::pthread_rwlock_tryrdlock(&mo_pthread_rwlock_t); }/* int TryLockRead()*/ int LockWrite() { return ::pthread_rwlock_wrlock(&mo_pthread_rwlock_t); }/* int LockRead()*/ int LockWrite(const struct timespec& AR_TimeSpec) { return ::pthread_rwlock_timedwrlock(&mo_pthread_rwlock_t,&AR_TimeSpec); }/* int LockWrite(const struct timespec& AR_TimeSpec)*/ int LockWrite(long AL_MiliSec) { timespec VO_TimeSpec; VO_TimeSpec.tv_sec =time(NULL)+AL_MiliSec/1000; VO_TimeSpec.tv_nsec=(AL_MiliSec%1000)*1000*1000; return ::pthread_rwlock_timedwrlock(&mo_pthread_rwlock_t, &VO_TimeSpec); }/* int LockWrite(long AL_MiliSec)*/ int TryLockWrite() { return ::pthread_rwlock_trywrlock(&mo_pthread_rwlock_t); }/* int TryLockWrite()*/ int UnLock() { return ::pthread_rwlock_unlock(&mo_pthread_rwlock_t); }/* int UnLock()*/ int Close() { return ::pthread_rwlock_destroy(&mo_pthread_rwlock_t); }/* int Close()*/ public: };/* class ZCLockRW_Base*/ class ZCLockRW : public ZCLockRW_Base { protected: pthread_rwlockattr_t mo_pthread_rwlockattr_t; public : int InitAttr() { return ::pthread_rwlockattr_init(&mo_pthread_rwlockattr_t); }/* int InitAttr()*/ int Init() { return ::pthread_rwlock_init(&mo_pthread_rwlock_t, &mo_pthread_rwlockattr_t); }/* int Init()*/ bool SetShared(int AI_PShared=PTHREAD_PROCESS_PRIVATE) { return ::pthread_rwlockattr_setpshared(&mo_pthread_rwlockattr_t, AI_PShared)==ZNsEnum::ZEThread_OK; }/* bool SetShared(int AI_PShared=PTHREAD_PROCESS_PRIVATE)*/ bool GetShared(int& ARRI_PShared) { return ::pthread_rwlockattr_getpshared(&mo_pthread_rwlockattr_t, &ARRI_PShared)==ZNsEnum::ZEThread_OK; }/* bool GetShared(int& ARRI_PShared)*/ // ÆÇµ¶ÀÚ,±â·ÏÀÚ lock ÀÇ ¿ì¼±¼øÀ§ °ü·Ã ÇÔ¼ö, ÇöÀç Posix Ç¥ÁØÀÌ ¾Æ´Ï´Ù. // ÀÌ ÇÔ¼ö·Î ¿ì¼±¼øÀ§¸¦ ¼³Á¤ÇÏÁö ¾Ê¾Ò´Ù¸é ±âº»ÀûÀ¸·Î ±â·ÏÀÚ lock ¿¡ // ¿ì¼±¼øÀ§¸¦ µÎ´Â °ÍÀ¸·Î ¼³Á¤µÇÀÖ´Â º£Æ÷ÆÇÀÌ ¸¹´Ù. -- 2006-12-30 16:21:00 int GetKind(int& ARRI_Kind) const { return ::pthread_rwlockattr_getkind_np(&mo_pthread_rwlockattr_t, &ARRI_Kind); }/* int GetKind(int& ARRI_Kind) const*/ int SetKind(int AI_Kind=PTHREAD_RWLOCK_PREFER_READER_NP) { return ::pthread_rwlockattr_setkind_np(&mo_pthread_rwlockattr_t, AI_Kind); }/* int SetKind(int AI_Kind=PTHREAD_RWLOCK_PREFER_READER_NP)*/ int CloseAttr() { return ::pthread_rwlockattr_destroy(&mo_pthread_rwlockattr_t); }/* int CloseAttr()*/ int Close() { return (ZCLockRW_Base::Close(), CloseAttr()); }/* int Close()*/ public: };/* class ZCLockRW*/ class ZCLockRW_Process { protected: ZCLockRW* mp_CLockRW ; ZCShareMemory mo_CShareMemory; public : ZCLockRW_Process() { mp_CLockRW=0; }/* ZCLockRW_Process()*/ bool Make(long AL_MapKey) { if(mo_CShareMemory.ShmGet(AL_MapKey,sizeof(ZCLockRW))==false) { if(errno!=EEXIST || mo_CShareMemory.ShmGet(AL_MapKey)!=true) { return false; } if(mo_CShareMemory.LinkMap()==false) { mo_CShareMemory.Close(); return false; }/* if(mo_CShareMemory.LinkMap()==false)*/ mp_CLockRW=(ZCLockRW*)mo_CShareMemory.GetStartAddress(); } else //!(mo_CShareMemory.ShmGet(AL_MapKey,sizeof(ZCLockRW))==false) { if(mo_CShareMemory.LinkMap()==false) { mo_CShareMemory.Close(); return false; }/* if(mo_CShareMemory.LinkMap()==false)*/ mp_CLockRW=(ZCLockRW*)mo_CShareMemory.GetStartAddress(); ::memset(mp_CLockRW,0x00,sizeof(ZCLockRW)); mp_CLockRW->InitAttr(); mp_CLockRW->SetShared(PTHREAD_PROCESS_SHARED); mp_CLockRW->Init(); }/* else //!(mo_CShareMemory.ShmGet(AL_MapKey,sizeof(ZCLockRW))==false)*/ return true; }/* bool Make(long AL_MapKey)*/ bool Make(const char* AP_KeyName) { int Index =-1 ; long VL_KeyID = 10 ; if(AP_KeyName!=0) { while(AP_KeyName[++Index]!=0) { VL_KeyID += AP_KeyName[Index]*(Index+1) ; }/* while(AP_KeyName[++Index]!=0)*/ }/* if(AP_KeyName!=0)*/ return this->Make(VL_KeyID); }/* bool Make(const char* AP_KeyName)*/ int LockRead() { return mp_CLockRW->LockRead(); }/* int LockRead()*/ int LockRead(const struct timespec& AR_TimeSpec) { return mp_CLockRW->LockRead(AR_TimeSpec); }/* int LockRead(const struct timespec& AR_TimeSpec)*/ int TryLockRead() { return mp_CLockRW->TryLockRead(); }/* int TryLockRead()*/ int LockWrite() { return mp_CLockRW->LockWrite(); }/* int LockRead()*/ int LockWrite(const struct timespec& AR_TimeSpec) { return mp_CLockRW->LockWrite(AR_TimeSpec); }/* int LockWrite(const struct timespec& AR_TimeSpec)*/ int TryLockWrite() { return mp_CLockRW->TryLockWrite(); }/* int TryLockWrite()*/ int UnLock() { return mp_CLockRW->UnLock(); }/* int UnLock()*/ int GetKind(int& ARRI_Kind) const { return mp_CLockRW->GetKind(RR(ARRI_Kind)); }/* int GetKind(int& ARRI_Kind) const*/ int SetKind(int AI_Kind=PTHREAD_RWLOCK_PREFER_READER_NP) { return mp_CLockRW->SetKind(AI_Kind); }/* int SetKind(int AI_Kind=PTHREAD_RWLOCK_PREFER_READER_NP)*/ int Close() { int VI_Resutl=mp_CLockRW->Close(); mo_CShareMemory.UnMap(); mo_CShareMemory.Close(); return VI_Resutl; }/* int Close()*/ public: };/* class ZCLockRW_Process*/ #endif //__USE_XOPEN2K /*////////////////////////////////////////////////////////////////////////////////// ¡á class ZCProcessSemaphore ´Â ÇÁ·Î¼¼½º¸¸À» À§ÇÑ µ¿±âÈ­ object. ¸®´ª½º¿¡¼­´Â ÇÁ·Î¼¼½º µ¿±âÈ­¿¡ Semaphore ¸¸ ¾µ ¼ö ÀÖ°í, Window ¿¡¼­´Â ÇÁ·Î¼¼½º µ¿±âÈ­¿¡ Mutex µµ ¾µ ¼ö ÀÖ´Ù. ¸®´ª½º¿¡¼­´Â ÇÁ·Î¼¼½º µ¿±âÈ­¿¡ ¾²ÀÌ´Â Semaphore ¿Í ½º·¹µå µ¿±âÈ­¿¡ ¾²ÀÌ´Â ¼¼¸¶Æ÷¾î°¡ ÇÔ¼ö¿Í ¿ë¹ýÀÌ ´Ù¸£´Ù. ¡á ½Ã½ºÅÛ È£Ãâ : semget() (SYSTEM CALL:semget()) »õ·Î¿î ¼¼¸¶ÆÛ ÁýÇÕÀ» ¸¸µé°Å³ª Á¸ÀçÇÏ´Â ÁýÇÕ¿¡ Á¢±ÙÇϱâ À§ÇÏ¿©, semget() ½Ã½ºÅÛ È£Ãâ À» »ç¿ëÇÑ´Ù. SYSTEM CALL: semget(); PROTOTYPE: int semget ( key_t key, int nsems, int semflg ); RETURNS: semaphore set IPC identifier on success -1 on error: errno = EACCESS (permission denied) EEXIST (set exists, cannot create (IPC_EXCL)) EIDRM (set is marked for deletion) ENOENT (set does not exist, no IPC_CREAT was used) ENOMEM (Not enough memory to create new set) ENOSPC (Maximum set limit exceeded) ¡à NOTES: semget()ÀÇ Ã¹¹øÂ° ¾Æ±Ô¸ÕÆ®´Â ftok()ÀÇ È£Ãâ¿¡ ÀÇÇØ ¹ÝȯµÈ ۰ªÀÌ´Ù. ÀÌ Å°°ªÀº Ä¿³Î¾È¿¡ Á¸ÀçÇÏ´Â ´Ù¸¥ ¼¼¸¶ÆÛ ÁýÇÕÀÇ Å°°ª°ú ºñ±³µÈ´Ù. À̶§ ¿­°Å³ª Á¢±ÙÇÏ´Â µ¿ÀÛÀº semflg ¾Æ±Ô¸ÕÆ®ÀÇ ³»¿ë¿¡ µû¶ó °áÁ¤µÈ´Ù. IPC_CREAT Ä¿³Î¾È¿¡ ÀÌ¹Ì Á¸ÀçÇÏÁö ¾Ê´Â´Ù¸é ¼¼¸¶ÆÛ ÁýÇÕÀ» ¸¸µç´Ù. IPC_EXCL IPC_CREAT¿Í °°ÀÌ »ç¿ëµÇ¾î, ¼¼¸¶ÆÛ°¡ ÀÌ¹Ì Á¸ÀçÇÏ¸é ½ÇÆÐÇÑ´Ù. IPC_CREAT°¡ È¥ÀÚ »ç¿ëµÈ´Ù¸é, semget()Àº »õ·Î ¸¸µé¾îÁø ÁýÇÕÀÇ ¼¼¸¶ÆÛ ÁýÇÕ È®ÀÎÀÚ (the semaphore set identifier)¸¦ ¹ÝȯÇϰųª °°Àº ۰ªÀ» °¡Áö°í ÀÌ¹Ì Á¸ÀçÇÏ´Â ÁýÇÕÀÇ È®ÀÎÀÚ¸¦ ¹ÝȯÇÑ´Ù. IPC_EXCL°¡ IPC_CREAT¿Í ÇÔ²² ¾²¿´´Ù¸é, »õ ÁýÇÕÀ» ¸¸µé°Å³ª ÀÌ¹Ì ÁýÇÕÀÌ Á¸ÀçÇÑ´Ù¸é -1 °ªÀ» °¡Áö°í È£Ãâ¿¡ ½ÇÆÐÇÑ´Ù. IPC_EXCLÀº ±× ÀÚü·Î´Â Àǹ̰¡ ¾øÁö¸¸, IPC_CREAT¿Í Á¶ÇÕµÇ¾î ¾²¿©Áú ¶§ Á¸ÀçÇÏÁö¾Ê´Â ¼¼¸¶ÆÛ¸¦ Á¢±Ù(access)Çϱâ À§ÇØ ¿­·ÁÁö´Â °ÍÀ» ¸·´Â ÀåÄ¡·Î »ç¿ëµÉ ¼ö ÀÖ´Ù. ½Ã½ºÅÛ V IPCÀÇ ´Ù¸¥ Çüŵéó·³ ºÎ°¡ÀûÀÎ 8Áø ¸ðµå°¡ ¼¼¸¶ÆÛ ÁýÇÕÀÇ Çã°¡»çÇ× ÇüÅ¿¡ ¸¶½ºÅ©·Î ORµÉ ¼ö ÀÖ´Ù. nsems ¾Æ±Ô¸ÕÆ®´Â »õ ÁýÇվȿ¡¼­ ¸¸µé¾îÁ®¾ß ÇÏ´Â ¼¼¸¶ÆÛÀÇ °¹¼ö¸¦ ÁöÁ¤ÇÑ´Ù. À̰ÍÀº ¾Õ¿¡¼­ ¼³¸íÇß´ø °¡»óÀÇ ÀÎ¼â¹æÀÇ ÇÁ¸°ÅÍÀÇ °¹¼ö¸¦ ÀǹÌÇÑ´Ù. ÁýÇÕ¾ÈÀÇ ÃÖ´ë ¼¼¸¶ÆÛÀÇ °¹¼ö´Â linux/sem.h¿¡ Á¤ÀÇ µÇ¾îÀÖ´Ù. #define SEMMSL 32 // <=512 id´ç ¼¼¸¶ÆÛÀÇ ÃÖ´ë °¹¼ö ÀÌ¹Ì Á¸ÀçÇÏ´Â ÁýÇÕÀ» ¸íÈ®È÷ ¿­°í ÀÖ´Ù¸é, nsems ¾Æ±Ô¸ÕÆ®´Â ¹«½ÃµÊ¿¡ ÁÖ¸ñÇØ¶ó. ¼¼¸¶ÆÛ ÁýÇÕÀ» ¸¸µé°í ¿©´Â wrapper ÇÔ¼ö¸¦ ¸¸µé¾î º¸ÀÚ: int open_semaphore_set( key_t keyval, int numsems ) { int sid; if ( ! numsems ) return(-1); if((sid = semget( mykey, numsems, IPC_CREAT | 0660 )) == -1) return(-1); //endif return(sid); } //int open_semaphore_set( key_t keyval, int numsems ) 0600ÀÇ ¸í½ÃÀûÀÎ Çã°¡»çÇ×À» »ç¿ëÇÔ¿¡ ÁÖÀÇÇØ¶ó. ÀÌ ÀÛÀº ÇÔ¼ö´Â ¼¼¸¶ÆÛ ÁýÇÕ È®ÀÎÀÚ(int)¸¦ ¹ÝȯÇϰųª ¿¡·¯½Ã -1À» ¹ÝȯÇÑ´Ù. »õ ÁýÇÕÀÌ ¸¸µé¾îÁ³´Ù¸é, °ø°£À» ÇÒ´çÇϱâ À§ÇØ ¼¼¸¶ÆÛÀÇ °¹¼ö¿Í ¸¶Âù°¡Áö·Î ۰ªÀÌ ³Ñ°ÜÁ®¾ß ÇÑ´Ù. ÀÌÀåÀÇ ³¡¿¡¼­ Ç¥ÇöµÉ ¿¹Á¦¿¡¼­, ¼¼¸¶ÆÛ ÁýÇÕÀÌ Á¸ÀçÇÏ´ÂÁö Á¸ÀçÇÏÁö ¾Ê´ÂÁö¸¦ °áÁ¤Çϱâ À§ÇÑ IPC_EXCL Ç÷¡±×ÀÇ »ç¿ë¿¡ ÁÖ¸ñÇØ¶ó ¡à -- NOTES -- ¡á int semctl ( int semid, int semnum, int cmd, union semun arg ); -1 on error: errno = EACCESS (permission denied) EFAULT(invalid address pointed to by arg argument) EIDRM (semaphore set was removed) EINVAL(set doesn't exist, or semid is invalid) EPERM (EUID has no privileges for cmd in arg) ERANGE(semaphore value out of range) ¡à semctl() ÇÔ¼öÀÇ 3 ¹øÂ° Àμö°¡ °¡Áú ¼ö ÀÖ´Â ¿©·¯ °ª IPC_STAT ÁýÇÕ¿¡ ´ëÇÑ semid_ds ±¸Á¶¸¦ Á¶È¸Çϰí, semun union¾ÈÀÇ buf ¾Æ±Ô¸ÕÆ®ÀÇ ÁÖ¼ÒÁö¿¡ ÀúÀåÇÑ´Ù. IPC_SET ÁýÇÕ¿¡ ´ëÇÑ semid_ds ±¸Á¶ÀÇ ipc_perm ¸â¹öÀÇ °ªÀ» ÁöÁ¤ÇÑ´Ù. semum unionÀÇ buf ¾Æ±Ô¸ÕÆ®·Î ºÎÅÍ °ªÀ» °¡Á®¿Â´Ù. IPC_RMID Ä¿³Î·Î ºÎÅÍ ÁýÇÕÀ» Á¦°ÅÇÑ´Ù. GETALL ÁýÇÕÀ¸·Î ºÎÅÍ ¸ðµç ¼¼¸¶ÆÛÀÇ °ªÀ» ¾ò´Âµ¥ »ç¿ëµÈ´Ù. Á¤¼ö°ªµéÀÌ unionÀÇ ¹è¿­ ¸â¹ö¿¡ ÀÇÇØ ÁöÁ¤µÈ unsigned short integer ¹è¿­¿¡ ÀúÀåµÈ´Ù. GETCNT ÀÚ¿ø¿¡ ´ëÇØ ÇöÀç ±â´Ù¸®°í ÀÖ´Â ÇÁ·Î¼¼½ºÀÇ ¼ö¸¦ ¹ÝȯÇÑ´Ù. GETPID ¸¶Áö¸· semop È£ÃâÀ» ¼öÇàÇÑ ÇÁ·Î¼¼½ºÀÇ PID¸¦ ¹ÝȯÇÑ´Ù. GETZCNT 100% ÀÚ¿ø Ȱ¿ëÀ» À§ÇØ ÇöÀç ±â´Ù¸®°í ÀÖ´Â ÇÁ·Î¼¼½ºÀÇ ¼ö¸¦ ¹ÝȯÇÑ´Ù. SETALL ÁýÇÕ¾ÈÀÇ ¸ðµç ¼¼¸¶ÆÛÀÇ °ªÀ» unionÀÇ ¹è¿­ ¸â¹ö¾È¿¡ Æ÷ÇÔµÈ ¸ÅĪµÇ´Â °ªÀ¸·Î ÁöÁ¤ÇÑ´Ù. SETVAL ÁýÇÕ¾ÈÀÇ °³º°ÀûÀÎ ¼¼¸¶ÆÛÀÇ °ªÀ» unionÀÇ val ¸â¹öÀÇ °ªÀ¸·Î ÁöÁ¤ÇÑ´Ù. ¡á arg ¾Æ±Ô¸ÕÆ®´Â semun ŸÀÔÀÇ ¿¹¸¦ ³ªÅ¸³½´Ù. ÀÌ Æ¯º°ÇÑ ¿¬ÇÕü(union)´Â linux/sem.h¿¡ ´ÙÀ½°ú °°ÀÌ ¼±¾ðµÇ¾îÀÖ´Ù. union semun { int val; // SETVALÀ» À§ÇÑ °ª struct semid_ds *buf; // IPC_STAT & IPC_SETÀ» À§ÇÑ ¹öÆÛ ushort *array; // GETALL & SETALL¸¦ À§ÇÑ ¹è¿­ struct seminfo *__buf; // IPC_INFO¸¦ À§ÇÑ ¹öÆÛ void *__pad; }; val SETVAL ¸í·É¾î°¡ ¼öÇàµÉ ¶§ »ç¿ëµÈ´Ù.¼¼¸¶ÆÛ¿¡ ÁöÁ¤µÉ °ªÀ» ÁöÁ¤ÇÑ´Ù. buf IPC_STAT/IPC_SET¿¡¼­ »ç¿ëµÈ´Ù. Ä¿³Î¾È¿¡¼­ »ç¿ëµÇ´Â ³»ºÎ ¼¼¸¶ÆÛ ÀÚ·á ±¸Á¶ÀÇ º¹»çº»À» ³ªÅ¸³½´Ù. array GETALL/SETALL ¸í·É¾î¿¡¼­ »ç¿ëµÇ´Â Æ÷ÀÎÅÍ. ÁýÇվȿ¡¼­ ¸ðµç ¼¼¸¶ÆÛ °ªµéÀ» Á¶È¸Çϰųª ÁöÁ¤Çϴµ¥ »ç¿ëµÇ´Â Á¤¼ö°ªµéÀÇ ¹è¿­À» °¡¸®Å°°í ÀÖ¾î¾ß ÇÑ´Ù. ³²¾ÆÀÖ´Â ¾Æ±Ô¸ÕÆ®ÀÎ _buf¿Í _pad´Â Ä¿³Î ¾ÈÀÇ ¼¼¸¶ÆÛ Äڵ峻¿¡¼­ ³»ºÎÀûÀ¸·Î »ç¿ëµÇ¸ç ÀÀ¿ëÇÁ·Î±×·¥ °³¹ßÀÚ¿¡°Ô´Â °ÅÀÇ ¾µ¸ð°¡ ¾ø´Ù. »ç½Ç»ó, ÀÌ·± µÎ°³ÀÇ ¾Æ±Ô¸ÕÆ®´Â ¸®´ª½º ¿î¿µÃ¼Á¦¿¡¼­ ÁöÁ¤µÇ¸ç ´Ù¸¥ À¯´Ð½º ±¸Çö¿¡¼­´Â ãÀ» ¼ö ¾ø´Ù. ÀÌ·± Ưº°ÇÑ ½Ã½ºÅÛ È£ÃâÀ» ¸ðµç ½Ã½ºÅÛ V IPC È£ÃâÀ» ÀÌÇØÇϴµ¥ °¡Àå ¾î·Á¿î Á¡À¸·Î ²ÅÀ» ¼ö ÀÖÀ¸¹Ç·Î,½ÇÁ¦·Î ÀÌ·¯ÇÑ ´Ù¾çÇÑ ¿¹¸¦ °Ë»çÇÒ °ÍÀÌ´Ù. ¸¶Áö¸· ¾Æ±Ô¸ÕÆ®(union)Àº GETVAL ¸í·É¾î°¡ »ç¿ëµÉ ¶§ ¹«½ÃµÈ´Ù. ¡á Posix Çü Semaphore ´Â unistd.h Çì´õ ÆÄÀÏ¿¡ _POSIX_SEMAPHORES ¿É¼ÇÀÌ Á¤ÀǵǾúÀ¸¸é »ç¿ëÇÒ ¼ö ÀÖ´Ù. -- POSIX(Æ÷Á÷½º) ¾²·¹µå¸¦ ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹Ö (2011-05-23 20:31:00) //////////////////////////////////////////////////////////////////////////////////*/ class ZCProcessSemaphore { private: ZTypeID mh_Semaphore; public : ZCProcessSemaphore() { mh_Semaphore=0; }/* ZCProcessSemaphore()*/ // Linux ¿¡¼­´Â ¼¼¸¶Æ÷¾î¸¦ ¹è¿­·Î ¼±¾ðÇÒ ¼ö ÀÖÀ¸³ª // °ÅÀÇ ¾µ ÀÏÀÌ ¾ø°í ¿ø¼Ò ÇϳªÀÇ ¹è¿­·Î »ç¿ëÇÑ´Ù. bool Make(const char* AP_SemaName, long AL_InitialCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return this->Make(ZNsMain::ZfGetKeyNum(AP_SemaName), AL_InitialCnt, AI_Flag); }/* bool Make(const char* AP_SemaName, long AL_InitialCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool Make(long AL_KeyID,int AL_InitialCnt,int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { if((mh_Semaphore=semget((key_t)AL_KeyID,1,AI_Flag))==-1) { if(errno==EEXIST) return (mh_Semaphore=semget((key_t)AL_KeyID,1,0))!=-1 ; return false; }/* if((mh_Semaphore=semget((key_t)AL_KeyID,1,AI_Flag))==-1)*/ union semun SemUnion; SemUnion.val=AL_InitialCnt; return semctl(mh_Semaphore, 0, SETVAL,SemUnion) != -1 ; }/* bool Make(long AL_KeyID,int AL_InitialCnt,int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ // ¾Æ·¡ ÇÔ¼ö´Â ¹ÂÅØ½ºÃ³·³ »ç¿ëÇϴµ¥ ÁÁ´Ù. bool Make(int AL_InitialCnt=1, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return Make(this->GetUniqueSemaKey(), AL_InitialCnt, AI_Flag); }/* bool Make(int AL_InitialCnt=1, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ // ºñ½ÅÈ£»óÅÂÀÇ ¼¼¸¶Æ÷¾î¸¦ ¸¸µç´Ù. bool MakeZero(int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return Make(this->GetUniqueSemaKey(), 0, AI_Flag); }/* bool MakeZero(int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ static long GetUniqueSemaKey() { static long SL_UniqueID=0 ; const long CL_AddID =100000; return ( SL_UniqueID += CL_AddID ) + ::getpid() ; }/* static long GetUniqueSemaKey()*/ bool MakeArr(long AL_KeyID, int AL_InitialCnt, int AI_SemaCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { if((mh_Semaphore=semget((key_t)AL_KeyID, AI_SemaCnt, AI_Flag))==-1) { if(errno==EEXIST) return (mh_Semaphore=semget((key_t)AL_KeyID, AI_SemaCnt,0))!=-1 ; return false; }/* if((mh_Semaphore=semget((key_t)AL_KeyID, AI_SemaCnt, AI_Flag))==-1)*/ union semun SemUnion; SemUnion.val=AL_InitialCnt; // ÃʱâÈ­´Â SETALL ¿É¼ÇÀ» »ç¿ëÇØµµ µÇ´Âµ¥ SemUnion.array ¿¡ ¹è¿­À» ÇÒ´çÇϰí // ÃʱâÈ­ÇÏ°í ´ëÀÔÇÏ´Â °úÁ¤À» »ý°¢ÇÏ¸é ±×³É for ¹®À¸·Îµµ »ó°ü¾øÀ» °Í °°´Ù. __for0(ZTypInt, i, AI_SemaCnt) { if(semctl(mh_Semaphore, i, SETVAL,SemUnion) != -1 ) return false; }/* __for0(ZTypInt, i, AI_SemaCnt)*/ return true; }/* bool MakeArr(long AL_KeyID, int AL_InitialCnt, int AI_SemaCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool MakeArr(const char* AP_SemaName, int AL_InitialCnt, int AI_SemaCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return MakeArr(ZNsMain::ZfGetKeyNum(AP_SemaName), AL_InitialCnt, AI_SemaCnt, AI_Flag); }/* bool MakeArr(const char* AP_SemaName, int AL_InitialCnt, int AI_SemaCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ // bool MakeStd() ´Â class ZCProcessSemaphore °¡ Window, Linux ¾çÂÊ¿¡¼­ ȣȯÇϱâ À§ÇÑ °Í, // Àμö AI_MaxSemaCnt ´Â »ç¿ëÇÏÁö ¾Ê°í ÀÖ´Ù.(Window ¿¡¼­¸¸ Àǹ̰¡ ÀÖ´Ù.) bool MakeStd(const char* AP_SemaName, int AL_InitialCnt, int AI_MaxSemaCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664) { return this->Make(ZNsMain::ZfGetKeyNum(AP_SemaName), AL_InitialCnt, AI_Flag); }/* bool MakeStd(const char* AP_SemaName, int AL_InitialCnt, int AI_MaxSemaCnt, int AI_Flag=IPC_CREAT | IPC_EXCL | 0664)*/ bool Open(const char* AP_SemaName) { return (mh_Semaphore=semget((key_t)(ZNsMain::ZfGetKeyNum(AP_SemaName)), 1, 0))>0 ; }/* bool Open(const char* AP_SemaName)*/ // ÇöÀç ¼¼¸¶Æ÷¾îÀÇ °ªÀ» °¡Á®¿Â´Ù. int GetValue(int AI_SemaNum=0) { return semctl(mh_Semaphore, AI_SemaNum, GETVAL, 0/*union semun arg*/) ; }/* int GetValue(int AI_SemaNum=0)*/ bool GetValue(union semun& ARR_SemUnion) { return semctl(mh_Semaphore, 0/*ignored*/, GETALL, ARR_SemUnion) !=-1 ; }/* bool GetValue(union semun& ARR_SemUnion)*/ bool IsZeroCount() { return this->GetValue()==0; }/* bool IsZeroCount()*/ bool Lock(ZTypUInt AI_ReleaseCount=1) { return LockRaw(AI_ReleaseCount)!=-1; }/* bool Lock(ZTypUInt AI_ReleaseCount=1)*/ // LockRaw() ´Â ¼º°øÀ̸é ZEThread_OK, ½Ã°£ Ãʰú´Â ZEThread_TimeOut À» ¹ÝȯÇÑ´Ù. // ¸®´ª½ºÀÇ Posix ¼¼¸¶Æ÷¾î¿¡¼­µµ °°´Ù. int LockRaw(ZTypUInt AI_ReleaseCount=1) { // cf) Window ÀÇ ReleaseSemaphore(mh_Semaphore,lReleaseCount,lpPreviousCount) ¿¡¼­ // µÎ¹øÂ° ÀμöÀÇ ¿ªÇÒÀ» AI_ReleaseCount °¡ ÇÑ´Ù. struct sembuf sem_b; sem_b.sem_num= 0 ; sem_b.sem_op =-AI_ReleaseCount; sem_b.sem_flg= SEM_UNDO ; return semop(mh_Semaphore, &sem_b,1) ; }/* int LockRaw(ZTypUInt AI_ReleaseCount=1)*/ bool UnLock(ZTypUInt AI_ReleaseCount=1) { // cf) Window ÀÇ ReleaseSemaphore(mh_Semaphore,lReleaseCount,lpPreviousCount) ¿¡¼­ // µÎ¹øÂ° ÀμöÀÇ ¿ªÇÒÀ» AI_ReleaseCount °¡ ÇÑ´Ù. struct sembuf sem_b; sem_b.sem_num=0; sem_b.sem_op =AI_ReleaseCount; sem_b.sem_flg=SEM_UNDO; return semop(mh_Semaphore, &sem_b,1)!=-1 ; }/* bool UnLock(ZTypUInt AI_ReleaseCount=1)*/ bool Close() { union semun SemUnion; bool VB_IsOK = (semctl(mh_Semaphore, 0, IPC_RMID ,SemUnion)!=-1) ; mh_Semaphore=0; return VB_IsOK; }/* bool Close()*/ public: };/* class ZCProcessSemaphore*/ /////////////////////////////////////////////// /////////// end class ZCProcessMutex /////////// /////////////////////////////////////////////// /*///////////////////////////////////////////// #define SEM_FAILED 0 #define SEM_VALUE_MAX 1147483648 int sem_init (sem_t * sem, int pshared, unsigned int value); int sem_destroy (sem_t * sem); sem_t *sem_open (const char *name, int oflag, ...); int sem_close (sem_t *sem); int sem_wait (sem_t * sem); int sem_trywait (sem_t * sem); int sem_timedwait (sem_t * sem, const struct timespec *abstime); int sem_post (sem_t * sem); int sem_getvalue(sem_t * sem, int *sval); cf) #include int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); DESCRIPTION The sem_wait() function locks the semaphore referenced by sem by performing a semaphore lock operation on that semaphore. If the semaphore value is currently zero, then the calling thread will not return from the call to sem_wait() until it either locks the semaphore or the call is interrupted by a signal. The sem_trywait() function locks the semaphore referenced by sem only if the semaphore is currently not locked; that is, if the semaphore value is currently positive. Otherwise, it does not lock the semaphore. Upon successful return, the state of the semaphore is locked and remains locked until the sem_post() function is executed and returns successfully. The sem_wait() function is interruptible by the delivery of a signal. HMUG - Mac OS X / Darwin man pages Current Directory /man/2 -------------------------------------------------------------------------------- NAME sem_open - initialize and open a named semaphore SYNOPSIS #include sem_t* sem_open(const char *name, int flags) sem_t* sem_open(const char *name, int flags, mode_t mode, unsigned int value) DESCRIPTION The named semaphore named name is initialized and opened as specified by the argument flags and a semaphore descriptor is returned to the calling process. The flags specified are formed by or'ing the following values: O_CREAT create the semaphore if it does not exist O_EXCL error if create and semaphore exists If O_CREATE if specified, sem_open() requires an additional two argu- ments. mode specifies the permissions for the semaphore as described in chmod(2) and modified by the process' umask value (see umask(2)). The semaphore is created with an initial value, which must be less than or equal to SEM_VALUE_MAX. If O_EXCL is specified and the semaphore exists, sem_open() fails. The check for the existence of the semaphore and the creation of the semaphore are atomic with respect to all processes calling sem_open() with O_CREAT and O_EXCL set. When a new semaphore is created, it is given the user ID and group ID which coorespond to the effective user and group IDs of the calling pro- cess. There is no visible entry in the file system for the created object in this implementation. The returned semaphore descriptor is available to the calling process un- til it is closed with sem_close(), or until the caller exits or execs. If a process makes repeated calls to sem_open(), with the same name argu- ment, the same descriptor is returned for each successful call, unless sem_unlink() has been called on the semaphore in the interim. If sem_open() fails for any reason, it will return a value of SEM_FAILED and sets errno. On success, it returns a semaphore descriptor. ERRORS The named semaphore is opened unless: [EACCES] The required permissions (for reading and/or writing) are denied for the given flags; or O_CREAT is specified, the object does not exist, and permission to create the semaphore is denied. [EEXIST] O_CREAT and O_EXCL were specified and the semaphore exists. [EINTR] The sem_open() operation was interrupted by a signal. [EINVAL] The shm_open() operation is not supported; or O_CREAT is specified and value exceeds SEM_VALUE_MAX. [EMFILE] The process has already reached its limit for semaphores or file descriptors in use. [ENAMETOOLONG] name exceeded SEM_NAME_LEN characters. [ENFILE] Too many semaphores or file descriptors are open on the system. [ENOENT] O_CREAT is not set and the named semaphore does not exist. [ENOSPC] O_CREAT is specified, the file does not exist, and there is insufficient space available to create the semaphore. SEE ALSO semctl(2), semget(2), semop(2), sem_close(2), sem_post(2), sem_trywait(2), sem_unlink(2), sem_wait(2), umask(2) HISTORY sem_open() is specified in the POSIX Realtime Extension (1003.1b-1993/1003.1i-1995). Darwin Operating System June 8, 2000 2 /////////////////////////////////////////////*/ /*////////////////////////////////////////////////////////// ¡á class ZCThreadSemaphore ´Â À©µµ¿ì¿Í »ó´çÈ÷ ȣȯµÇ±â ¾î·Æ´Ù. À©µµ¿ì¿Í ȣȯÀº class ZCProcessSemaphore ÀÌ ¾à°£ ÁÁ´Ù. ¡á sem_t ¿¡´Â 0 À» ´ëÀÔÇÒ ¼ö ¾ø´Ù. //////////////////////////////////////////////////////////*/ class ZCThreadSemaphore { private: sem_t mh_Semaphore; public : /*///////////////////////////////////////////////////////////////////////////// ¡á sem_init() ÇÔ¼ö´Â À̸§¾ø´Â ¼¼¸¶Æ÷¾î¸¦ ¸¸µé¶§ »ç¿ëÇÑ´Ù. À̸§ÀÖ´Â ¼¼¸¶Æ÷¾îÀÇ °æ¿ì sem_open() À» »ç¿ëÇØ¾ß Çϸç, ÆÄ±«ÇÒ ¶§µµ sem_close() ¿Í sem_unlink() ¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù. ÀÌ Å¬·¡½º¿¡¼­´Â À̸§¾ø´Â ¼¼¸¶Æ÷¾î¸¸ ´Ù·é´Ù. AI_Shared °¡ 0 ÀÌ ¾Æ´Ï¸é ´ÙÁß ÇÁ·Î¼¼½º¿¡¼­µµ »ç¿ëÇÒ ¼ö ÀÖÀ¸³ª ÇöÀç Linux ÀÇ sem_XXX °è¿­ÀÇ ÇÔ¼ö´Â ÀÌ ±â´ÉÀ» Áö¿øÇÏÁö ¾Ê°í ÀÖ´Ù.(2004.7.12) ¡á AI_InitValue==1 À̶ó¸é ¹ÂÅØ½ºÃ³·³ »ç¿ëÇÏ·Á´Â °æ¿ìÀÌ´Ù. 2007-09-30 14:32:00 /////////////////////////////////////////////////////////////////////////////*/ bool Make(int AI_InitValue=1,int AI_Shared=0) { return ::sem_init(&mh_Semaphore, AI_Shared, AI_InitValue) !=-1 ; }/* bool Make(int AI_InitValue=1,int AI_Shared=0);*/ bool MakeZero(int AI_Shared=0) { return ::sem_init(&mh_Semaphore,AI_Shared,0) !=-1 ; }/* bool MakeZero(int AI_Shared=0)*/ bool Lock() { return ::sem_wait(&mh_Semaphore)==0 ; }/* bool Lock()*/ int LockRaw() { return ::sem_wait(&mh_Semaphore); }/* int LockRaw()*/ #ifdef __USE_XOPEN2K // cf) int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout); int LockRaw(const struct timespec& AR_TimeOut) { // timeout À̸é errno °¡ ZNsEnum::ZEThread_TimeOut if(::sem_timedwait(&mh_Semaphore, &AR_TimeOut)!=ZNsEnum::ZEThread_OK) return errno; //endif return ZNsEnum::ZEThread_OK; }/* int Lock(const struct timespec& AR_TimeOut)*/ int LockRaw(long AL_MiliSec) { timespec VO_TimeSpec; VO_TimeSpec.tv_sec =time(NULL)+AL_MiliSec/1000; VO_TimeSpec.tv_nsec=(AL_MiliSec%1000)*1000*1000; return ::sem_timedwait(&mh_Semaphore,&VO_TimeSpec); }/* LockRaw LockRaw(long AL_MiliSec)*/ int LockTime(long AL_MiliSec) { return LockRaw(AL_MiliSec); }/* int LockTime(long AL_MiliSec)*/ #endif //__USE_XOPEN2K // sem_trywait() Àº ÀÌ¹Ì lock ÀÌ °É·Á ÀÖÀ¸¸é -1 À» // ¹ÝȯÇϰí, errno °¡ EAGAIN À¸·Î ¼ÂÆÃµÈ´Ù. bool TryLock() { return ::sem_trywait(&mh_Semaphore)==0 ; }/* bool TryLock()*/ bool UnLock() { return ::sem_post(&mh_Semaphore)==0 ; }/* bool UnLock()*/ // sem_destroy() ÇÔ¼ö´Â À̸§¾ø´Â ¼¼¸¶Æ÷¾îÀÇ Á¦°Å¿¡¸¸ »ç¿ëµÇ´Â ÇÔ¼ö´Ù. // À̸§ÀÖ´Â ¼¼¸¶Æ÷¾î¿¡ »ç¿ëÇÒ °æ¿ì¿¡ ±× ÇàÀ§´Â Á¤ÀǵǾî ÀÖÁö ¾Ê´Ù. bool Close() { return (sem_destroy(&mh_Semaphore)==0); }/* bool Close()*/ int GetValue() const { int VI_Val=0; const bool CB_IsOK = (::sem_getvalue((sem_t*)&mh_Semaphore, &VI_Val)!=0); if(CB_IsOK) return -1; return VI_Val; }/* int GetValue() const*/ public: };/* class ZCThreadSemaphore*/ // ¸®´ª½º ¾²·¹µå ¹ÂÅØ½º´Â º¹»çÇØ¼­ »ç¿ëÇÒ ¼ö ¾ø´Ù. class ZCThreadMutex { private : ZCThreadMutex(const ZCThreadMutex& rhs){} ZCThreadMutex& operator=(const ZCThreadMutex& rhs) { return *this; }/* ZCThreadMutex& operator=(const ZCThreadMutex& rhs)*/ /*private :*/ protected: pthread_mutex_t mo_Mutex; public : ZCThreadMutex() { }/* ZCThreadMutex()*/ const pthread_mutex_t& GetMutexID() const { return mo_Mutex; }/* const pthread_mutex_t& GetMutexID() const*/ pthread_mutex_t& GetMutexID() { return mo_Mutex; }/* pthread_mutex_t& GetMutexID()*/ bool Make(const pthread_mutexattr_t* AP_MutexAttr=0) { return pthread_mutex_init(&mo_Mutex, AP_MutexAttr)==0 ; }/* bool Make(const pthread_mutexattr_t* AP_MutexAttr=0)*/ bool Lock() { return this->LockRaw()==0 ; }/* bool Lock()*/ int LockRaw() { return pthread_mutex_lock(&mo_Mutex) ; }/* int LockRaw()*/ #ifdef __USE_XOPEN2K bool Lock(long AL_MiliSec) { return this->LockRaw(AL_MiliSec)==0 ; }/* bool Lock(long AL_MiliSec)*/ // cf) 30 Ãʰ£ LOCK // // struct timespec ts_timeout; // ts_timeout.tv_sec =time(NULL)+30; // ts_timeout.tv_nsec=0; int LockRaw(const struct timespec& AR_TimeOut) { return pthread_mutex_timedlock(&mo_Mutex, &AR_TimeOut) ; }/* int LockRaw(const struct timespec& AR_TimeOut)*/ int LockRaw(long AL_MiliSec) { timespec VO_TimeSpec; VO_TimeSpec.tv_sec = time(NULL)+AL_MiliSec/1000 ; VO_TimeSpec.tv_nsec= (AL_MiliSec%1000)*1000*1000 ; return pthread_mutex_timedlock(&mo_Mutex, &VO_TimeSpec) ; }/* int LockRaw(long AL_MiliSec)*/ int LockTime(long AL_MiliSec) { return LockRaw(AL_MiliSec); }/* int LockTime(long AL_MiliSec)*/ #endif //__USE_XOPEN2K int TryLock() { return pthread_mutex_trylock(&mo_Mutex); }/* int TryLock()*/ bool UnLock() { return pthread_mutex_unlock(&mo_Mutex)==0 ; }/* bool UnLock()*/ bool Close() { return pthread_mutex_destroy(&mo_Mutex)==0 ; }/* bool Close()*/ public: };/* class ZCThreadMutex*/ class ZCThreadMutexAttr { private: ZCThreadMutexAttr(const ZCThreadMutexAttr& rhs) { }/* ZCThreadMutexAttr(const ZCThreadMutexAttr& rhs)*/ ZCThreadMutexAttr& operator=(const ZCThreadMutexAttr& rhs) { return *this; }/* ZCThreadMutexAttr& operator=(const ZCThreadMutexAttr& rhs)*/ /*private :*/ protected: pthread_mutex_t mo_Mutex ; pthread_mutexattr_t mo_PThreadMutexAttr; public : ZCThreadMutexAttr() { }/* ZCThreadMutexAttr()*/ const pthread_mutex_t& GetMutexID() const { return mo_Mutex; }/* const pthread_mutex_t& GetMutexID() const*/ pthread_mutex_t& GetMutexID() { return mo_Mutex; }/* pthread_mutex_t& GetMutexID()*/ bool Make(int AI_ThreadType=PTHREAD_MUTEX_RECURSIVE) { // PTHREAD_MUTEX_RECURSIVE mutex ´Â °°Àº ¾²·¹µå¿¡¼­ ¼ÒÀ¯ÇÑ ¸¸Å­ ÇØÁ¦ÇؾßÇÑ´Ù. // µû¶ó¼­ Ŭ·¡½º »ý¼ºÀÚ¿¡¼­ ¼ÒÀ¯ÇÏ°í ¼Ò¸êÀÚ¿¡¼­ ÇØÁ¦Çϱ⿡ µü ÁÁ´Ù. if(pthread_mutexattr_init(&mo_PThreadMutexAttr)!=0) return false; if(pthread_mutexattr_settype(&mo_PThreadMutexAttr,AI_ThreadType)!=0) return false; if(pthread_mutexattr_setpshared(&mo_PThreadMutexAttr,PTHREAD_PROCESS_SHARED)!=0) return false; //endif /*/////////////////////////////////////////////////////////////////////////////// if(pthread_mutexattr_setpshared(&mo_PThreadMutexAttr,PTHREAD_PROCESS_PRIVATE)!=0) return false; //endif µµ °¡´ÉÇѵ¥, Mutex ¸¦ ÇÁ·Î¼¼½º »çÀÌ¿¡ °øÀ¯µÇ°Ô ÇÏ°í ½Í´Ù¸é PTHREAD_PROCESS_SHARED À» ±âº»°ªÀ¸·Î ÇÏ´Â °ÍÀÌ ¸Â´Ù. -- 2010-01-04 11:59:00 ///////////////////////////////////////////////////////////////////////////////*/ return pthread_mutex_init(&mo_Mutex,(const pthread_mutexattr_t*)&mo_PThreadMutexAttr)==0 ; }/* bool Make(int AI_ThreadType=PTHREAD_MUTEX_RECURSIVE)*/ bool Make(const pthread_mutexattr_t* AP_MutexAttr) { return pthread_mutex_init(&mo_Mutex, AP_MutexAttr)==0 ; }/* bool Make(const pthread_mutexattr_t* AP_MutexAttr)*/ bool Lock() { return this->LockRaw()==0 ; }/* bool Lock()*/ #ifdef __USE_XOPEN2K bool Lock(long AL_MiliSec) { return this->LockRaw(AL_MiliSec)==0 ; }/* bool Lock(long AL_MiliSec)*/ #endif //__USE_XOPEN2K int LockRaw() { return pthread_mutex_lock(&mo_Mutex) ; }/* int LockRaw()*/ // cf) 30 Ãʰ£ LOCK // // struct timespec ts_timeout; // ts_timeout.tv_sec=time(NULL)+30; // ts_timeout.tv_nsec=0; #ifdef __USE_XOPEN2K int LockRaw(const struct timespec& AR_TimeOut) { return pthread_mutex_timedlock(&mo_Mutex, &AR_TimeOut) ; }/* int LockRaw(const struct timespec& AR_TimeOut)*/ int LockRaw(long AL_MiliSec) { timespec VO_TimeSpec; VO_TimeSpec.tv_sec = time(NULL)+AL_MiliSec/1000 ; VO_TimeSpec.tv_nsec= (AL_MiliSec%1000)*1000*1000 ; return pthread_mutex_timedlock(&mo_Mutex, &VO_TimeSpec) ; }/* int LockRaw(long AL_MiliSec)*/ #endif //__USE_XOPEN2K int TryLock() { return pthread_mutex_trylock(&mo_Mutex); }/* int TryLock()*/ bool UnLock() { return pthread_mutex_unlock(&mo_Mutex)==0 ; }/* bool UnLock()*/ bool Close() { return pthread_mutexattr_destroy(&mo_PThreadMutexAttr)==0 && pthread_mutex_destroy (&mo_Mutex) ==0 ; /////// }/* bool Close()*/ public: };/* class ZCThreadMutexAttr*/ typedef ZCThreadMutexAttr ZCThreadMutexStd; class ZCThreadMutexEasy : protected ZCThreadMutex { public: ZCThreadMutexEasy() { if(this->ZCThreadMutex::Make()==false) { std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app); fileout<ZCThreadMutex::Make()==false)*/ }/* ZCThreadMutexEasy()*/ /*/////////////////////////////////////////////////////////////////////////////////////////////////////////// ¡á ¾Æ·¡ ¼±¾ð ZCThreadMutexEasy(const ZCThreadMutexEasy& rhs) : ZCThreadMutex() ¿¡¼­ ZCThreadMutex() ¸¦ »©¸é g++ 4.4.6 ¿¡¼­ -W ¿É¼ÇÀ» ÁÖ¸é, ¾Æ·¡ °æ°í ¸Þ½ÃÁö¸¦ º¼ ¼ö ÀÖ´Ù. warning: base class 'class std::ZCThreadMutex' should be explicitly initialized in the copy constructor À§ °æ°í ¸Þ½ÃÁö°¡ ÇÕ¸®ÀûÀ̶ó°í »ý°¢µÇ´Â °ÍÀÌ, ÄÄÆÄÀÏ·¯´Â ±âÃÊ Å¬·¡½ºÀÇ º¹»ç »ý¼ºÀÚ ZCThreadMutex(rhs) À» È£Ãâ ÇÒ °ÍÀ̶ó°í ¿¹»óÇ߱⠶§¹®ÀÏ °ÍÀÌ´Ù. -- 2013-05-05 06:49:00 ///////////////////////////////////////////////////////////////////////////////////////////////////////////*/ ZCThreadMutexEasy(const ZCThreadMutexEasy& rhs) : ZCThreadMutex() { if(this->ZCThreadMutex::Make()==false) { std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app); fileout<ZCThreadMutex::Make()==false)*/ }/* ZCThreadMutexEasy(const ZCThreadMutexEasy& rhs)*/ ~ZCThreadMutexEasy() { if(this->ZCThreadMutex::Close()==false) { std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app); fileout<ZCThreadMutex::Close()==false)*/ }/* ~ZCThreadMutexEasy()*/ using ZCThreadMutex::Lock ; using ZCThreadMutex::UnLock; public: };/* class ZCThreadMutexEasy*/ class ZCThreadMutexAttrEasy : protected ZCThreadMutexAttr { public: ZCThreadMutexAttrEasy() { if(this->ZCThreadMutexAttr::Make()==false) { std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app); fileout<ZCThreadMutexAttr::Make()==false)*/ }/* ZCThreadMutexAttrEasy()*/ /*/////////////////////////////////////////////////////////////////////////////////////////////////////////// ¡á ¾Æ·¡ ¼±¾ð ZCThreadMutexAttrEasy(const ZCThreadMutexAttrEasy&) : ZCThreadMutexAttr() ¿¡¼­ ZCThreadMutex() ¸¦ »©¸é g++ 4.4.6 ¿¡¼­ -W ¿É¼ÇÀ» ÁÖ¸é, ¾Æ·¡ °æ°í ¸Þ½ÃÁö¸¦ º¼ ¼ö ÀÖ´Ù. warning: base class 'class std::ZCThreadMutexAttr' should be explicitly initialized in the copy constructor À§ °æ°í ¸Þ½ÃÁö°¡ ÇÕ¸®ÀûÀ̶ó°í »ý°¢µÇ´Â °ÍÀÌ, ÄÄÆÄÀÏ·¯´Â ±âÃÊ Å¬·¡½ºÀÇ º¹»ç »ý¼ºÀÚ ZCThreadMutexAttr(rhs) À» È£ÃâÇÒ °ÍÀ̶ó°í ¿¹»óÇ߱⠶§¹®ÀÏ °ÍÀÌ´Ù. -- 2013-05-05 06:49:00 ///////////////////////////////////////////////////////////////////////////////////////////////////////////*/ ZCThreadMutexAttrEasy(const ZCThreadMutexAttrEasy&) : ZCThreadMutexAttr() { if(this->ZCThreadMutexAttr::Make()==false) { std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app); fileout<ZCThreadMutexAttr::Make()==false)*/ }/* ZCThreadMutexAttrEasy(const ZCThreadMutexAttrEasy&)*/ ~ZCThreadMutexAttrEasy() { if(this->ZCThreadMutexAttr::Close()==false) { std::fstream fileout("DEBUG.txt",std::ios::out | std::ios::app); fileout<ZCThreadMutexAttr::Close()==false)*/ }/* ~ZCThreadMutexAttrEasy()*/ using ZCThreadMutexAttr::Lock ; using ZCThreadMutexAttr::UnLock; public: };/* class ZCThreadMutexAttrEasy*/ /*///////////////////////////////////////////////////////// ¡á ¾Æ·¡ ±âº» ¹ÂÅØ½º ZCThreadMutexEasy Àº Àç±ÍÀûÀ¸·Î »ç¿ëÇÒ ¼ö ¾ø¾î¼­(Å×½ºÆ®ÇØ º¸¸é dead lock ÀÌ ¹ß»ýÇÑ´Ù) ´Ù¼Ò ºÒ ¾ÈÇÏ´Ù.(Window Mutex ¿¡ ºñÇØ¼­) typedef ZCThreadMutexEasy ZCDefLockEasy; ±×·¡¼­ ¾Æ·¡ ¼±¾ðÀ¸·Î ¹Ù²Û´Ù. -- 2009-07-28 16:27:00 Àç±ÍÀûÀ¸·Î Mutex ¸¦ »ç¿ëÇÏ´Â »óȲÀ» ¸¸µéÁö ¸»¾Æ¾ß ÇÑ´Ù. -- 2013-07-22 12:28:00 ¡á freebsd 8.2 ¿¡¼­ Å×½ºÆ®ÇÒ ¶§, ÀÚ²Ù pthread_mutexattr_setpshared( &mo_PThreadMutexAttr,PTHREAD_PROCESS_SHARED )!=0 °¡ µÇ´Â Çö»óÀÌ À־, ZCThreadMutexEasy ¸¦ »ç¿ëÇÒ ¼ö ¾ø ¾ú´Ù. ±×·¡¼­ __MUTEX_EASY_DEFAULT_LOCK__ °¡ Á¤ÀǵǾî ÀÖ À¸¸é, typedef ZCThreadMutexEasy ZCDefLockEasy; ¼±¾ðÀ» »ç¿ëÇÏ°Ô ÇÑ´Ù. -- 2011-05-19 22:00:00 ±âº»ÀûÀ¸·Î ZCThreadMutexEasy À» »ç¿ëÇϰí ZCThreadMutexAttrEasy Àº __MUTEX_ATTR_EASY_DEFAULT_LOCK__ ÀÌ Á¤ÀǵǾî ÀÖÀ» ¶§, »ç¿ëÇÏ´Â °ÍÀ¸·Î ÇÑ´Ù. -- 2015-09-02 21:05:00 /////////////////////////////////////////////////////////*/ #ifdef __MUTEX_ATTR_EASY_DEFAULT_LOCK__ typedef ZCThreadMutexAttrEasy ZCDefLockEasy; #else typedef ZCThreadMutexEasy ZCDefLockEasy; #endif #ifdef __USE_XOPEN2K /*/////////////////////////////////////////////////////////////////////// ¡á spin lock Àº ªÀº ½Ã°£ µ¿±âÈ­¿¡´Â °¡Àå ÁÁ´Ù. ±×·±µ¥ ÀϹÝÀûÀ¸·Î µ¿±âÈ­ ¿¡ ¹ÂÅØ½º¸¦ »ç¿ëÇÏÀÚ. spin lock Àº context switching ¿¡ ºÎ´ãÀÌ µÇ¾î¼­ ÀÚÄ© ¹ÝÀÀ¼Óµµ°¡ ´À·ÁÁú ¼ö ÀÖ´Ù. ½ÉÁö¾î ¸î Ãʾ¿ °É·¯¼­ »ç¿ë¸øÇÏ´Â °æ¿ì µµ ¹ß»ýÇÑ´Ù. ¡á ¹ÂÅØ½º°¡ ¾Æ´Ñ spin lock À¸·Î µ¿±âÈ­¸¦ ÇÏ´Â °æ¿ì¿¡´Â µ¿±âÈ­ ¿µ¿ªÀÌ Á¤¸» ªÀº ¼öÇà½Ã°£À» °¡Á®¾ß ÇÑ´Ù. µ¿±âÈ­ ¿µ¿ª¿¡¼­ Äֿܼ¡ Ãâ·ÂÇÏ´Â µîÀÇ '±ä ó¸®'°¡ ÀÖÀ¸¸é ¾ÆÁÖ ³ª»Ú´Ù. ¸ÖƼ ¾²·¹µå¿¡¼­ spin lock À¸·Î µ¿±âÈ­¸¦ ÇÒ ¶§, À§¿Í °°Àº ´Ù¼Ò '±ä ó¸®'¸¦ ÇÒ °æ¿ì, ÀÛ¾÷ ¾²·¹µå°¡ ÄÁÅØ½ºÆ® ½ºÀ§Äª À» Çϸ鼭 µ¿±âÈ­ ¿µ¿ªÀÌ ³¡³ªÁö ¾ÊÀ» ¼ö ÀÖ°í ¶Ç ´Ù¸¥ ÀÛ¾÷ ¾²·¹µåÀÇ µ¿±â È­ ¿µ¿ª¿¡¼­ cpu °¡ spin Çϰí ÀÖ´Ù¸é µ¿±âÈ­°¡ ³¡³ª´Â ½ÃÁ¡ÀÌ ´Ê¾îÁö°í, ½ÉÁö¾î´Â dead lock ¿¡ ºüÁú ¼öµµ ÀÖ´Ù. -- 2008-03-20 11:27:00 ///////////////////////////////////////////////////////////////////////*/ class ZCSpinLock { private: pthread_spinlock_t mh_SpinLock; public : int Init(int AI_ShareMode=PTHREAD_PROCESS_PRIVATE) { // ÇÁ·Î¼¼½º°£¿¡ spin lock À» °øÀ¯ÇÑ´Ù¸é PTHREAD_PROCESS_SHARED ¸¦ ÁØ´Ù. // ±×¸®°í pthread_spinlock_t µµ °øÀ¯¸Þ¸ð¸®¿¡ ÀÖ¾î¾ß ÇÑ´Ù. ÀýÂ÷°¡ º¹ÀâÇÏ´Ù. return pthread_spin_init(&mh_SpinLock,AI_ShareMode); }/* void Init(int AI_ShareMode=PTHREAD_PROCESS_PRIVATE)*/ int Close() { return pthread_spin_destroy(&mh_SpinLock); }/* void Close()*/ int Delete() // for windows compatability { return this->Close(); }/* void Delete()*/ int Lock() { return pthread_spin_lock(&mh_SpinLock); }/* void Lock()*/ int TryLock() { return pthread_spin_trylock(&mh_SpinLock); }/* void TryLock()*/ int UnLock() { return pthread_spin_unlock(&mh_SpinLock); }/* void UnLock()*/ public: };/* class ZCSpinLock*/ class ZCSpinLockEasy : protected ZCSpinLock { public: /*####################################################################### ¡á ¼Ò¸êÀÚ¸¦ Á¦¿ÜÇÑ °¢ ¸â¹ö ÇÔ¼ö ¼±¾ð¿¡ throw(ZtCExceptBase) À» ºÙ¿´´Âµ¥, g++ 7.3.0 ¿¡¼­ °æ°í°¡ ³ª¼­ Áö¿ü´Ù. CProcess_Linux.H:2429:25: warning: dynamic exception specifications are deprecated in C++11 [-Wdeprecated] ZCSpinLockEasy() throw(ZtCExceptBase) -- 2018-06-26 15:12:00 #######################################################################*/ ZCSpinLockEasy() /*throw(ZtCExceptBase)*/ { int VI_Return=this->Init(); if(VI_Return!=0) { throw ZtCExceptBase(VI_Return); }/* if(VI_Return!=0)*/ }/* ZCSpinLockEasy()*/ ZCSpinLockEasy(const ZCSpinLockEasy& rhs) { int VI_Return=this->Init(); if(VI_Return!=0) { throw ZtCExceptBase(VI_Return); }/* if(VI_Return!=0)*/ }/* ZCSpinLockEasy(const ZCSpinLockEasy& rhs)*/ void Lock() { int VI_Return=this->ZCSpinLock::Lock(); if(VI_Return!=0) { throw ZtCExceptBase(VI_Return); }/* if(VI_Return!=0)*/ }/* void Lock() throw(ZtCExceptBase)*/ void UnLock() { int VI_Return=this->ZCSpinLock::UnLock(); if(VI_Return!=0) { throw ZtCExceptBase(VI_Return); }/* if(VI_Return!=0)*/ }/* void UnLock() throw(ZtCExceptBase)*/ ~ZCSpinLockEasy() { this->Delete(); }/* ZCSpinLockEasy()*/ public: };/* class ZCSpinLockEasy : protected ZCSpinLock*/ typedef ZCSpinLock ZCCriticSect ; typedef ZCSpinLockEasy ZCCriticSectEasy; #else // !__USE_XOPEN2K typedef ZCThreadMutex ZCCriticSect ; typedef ZCThreadMutexEasy ZCCriticSectEasy; #endif //!__USE_XOPEN2K template class ZtCAutoKeyRev; /*//////////////////////////////////////////////// ¡á class ZtCAutoKey<> : Lock À» ¼³Á¤Çϰí ÇØÁ¦ÇÑ´Ù. ¿­°í ´ÝÀ» ¼ö ÀÖ´Â ¿­¼è¿Í °°¾Æ Key ¶ó°í ÇÏ¿´´Ù. -- ÀÌ·± ½ÄÀÇ ±â¹ýÀ» RAII Resource Acquisition Is Initialization ¶ó°í ÇÑ´Ù´Â °ÍÀ» ¾Ë¾Ò´Ù. -- 2015-03-10 15:08:00 ////////////////////////////////////////////////*/ template< typename TCriticSectEasy=ZCThreadMutexEasy > class ZtCAutoKey ///////////////////////////////////// { public : template friend class ZtCAutoKeyRev; private: ZtCAutoKey(const ZtCAutoKey&){} private: TCriticSectEasy& mr_SyncEasy; #ifdef _DEBUG_CAUTOKEY_ static int msi_CallCnt; #endif //_DEBUG_CAUTOKEY_ public: ZtCAutoKey(TCriticSectEasy& AR_SyncEasy):mr_SyncEasy(AR_SyncEasy) { #ifdef _DEBUG_CAUTOKEY_ cout<<"¢º¢º¢º¢º ZtCAutoKey:: ZtCAutoKey() "< class ZtCAutoKey */ #ifdef _DEBUG_CAUTOKEY_ template int ZtCAutoKey::msi_CallCnt = 0 ; #endif //_DEBUG_CAUTOKEY_ /*//////////////////////////////////////////////////////////////// ¡á ZtCAutoKeyRev<> ´Â ZtCAutoKey<> À» »ý¼ºÀÚ¿¡¼­ Àμö·Î ¹Þ¾Æ¼­ »ý ¼ºÀÚ¿¡¼­ Lock À» ÇØÁ¦Çϰí, ¼Ò¸êÀÚ¿¡¼­ ´Ù½Ã Lock À» °É¾î ÁØ´Ù. ±×·±µ¥ ÀÌ·¸°Ô ÇØ¾ß µÉ »óȲ ÀÚü¸¦ ¸¸µéÁö ¸»ÀÚ. ¾ïÁö·Î »ç¿ëÇÏ´Ù º¸¸é ÀÚÁÖ Dead Lock »óÅ¿¡ ºüÁø´Ù. ¡Ø 2008-04-09 21:01:00 ////////////////////////////////////////////////////////////////*/ template class ZtCAutoKeyRev { private: TAutoKey& mr_CAutoKey; public : ZtCAutoKeyRev(TAutoKey& AR_CAutoKey):mr_CAutoKey(AR_CAutoKey) { mr_CAutoKey.mr_SyncEasy.UnLock(); }/* ZtCAutoKeyRev(TAutoKey& AR_CAutoKey)*/ ~ZtCAutoKeyRev() { mr_CAutoKey.mr_SyncEasy.Lock(); }/* ~ZtCAutoKeyRev()*/ public: };/* template class ZtCAutoKeyRev */ #ifdef __USE_XOPEN2K class ZCSpinLockProcess { public : enum{EReturn_ShareMemNone = -2}; // ÇØ´ç °øÀ¯¸Þ¸ð¸® ¾øÀ½ enum{EReturn_ShareMemMapErr= -3}; // °øÀ¯¸Þ¸ð¸® Map ½ÇÆÐ private: pthread_spinlock_t* mph_SpinLock ; ZCShareMemory mo_CShareMemory; public : int Init(long AL_MemMapkey) { if(mo_CShareMemory.ShmGet(AL_MemMapkey, sizeof(pthread_spinlock_t))==false) { if(errno!=EEXIST || mo_CShareMemory.ShmGet(AL_MemMapkey)!=true) { return this->EReturn_ShareMemNone; }/* if(errno!=EEXIST || mo_CShareMemory.ShmGet(AL_MemMapkey)!=true)*/ if(this->mo_CShareMemory.LinkMap()==false) { this->mo_CShareMemory.Close(); return this->EReturn_ShareMemMapErr; }/* if(this->mo_CShareMemory.LinkMap()==false)*/ mph_SpinLock = (pthread_spinlock_t*)mo_CShareMemory.GetStartAddress(); return 0; } else // mo_CShareMemory.ShmGet(AL_MemMapkey, sizeof(pthread_spinlock_t))!=false { if(this->mo_CShareMemory.LinkMap()==false) { this->mo_CShareMemory.Close(); return this->EReturn_ShareMemMapErr; }/* if(this->mo_CShareMemory.LinkMap()==false)*/ mph_SpinLock=(pthread_spinlock_t*)mo_CShareMemory.GetStartAddress(); ::memset((void*)mph_SpinLock, 0x00, sizeof(pthread_spinlock_t)); return ::pthread_spin_init(mph_SpinLock, PTHREAD_PROCESS_SHARED); }/* else // mo_CShareMemory.ShmGet(AL_MemMapkey,sizeof(pthread_spinlock_t))!=false*/ }/* int Init(long AL_MemMapkey)*/ int Close() { mo_CShareMemory.UnMap(); mo_CShareMemory.Close(); return ::pthread_spin_destroy(mph_SpinLock); }/* void Close()*/ int Lock() { return ::pthread_spin_lock(mph_SpinLock); }/* void Lock()*/ int TryLock() { return ::pthread_spin_trylock(mph_SpinLock); }/* void TryLock()*/ int UnLock() { return ::pthread_spin_unlock(mph_SpinLock); }/* void UnLock()*/ public: };/* class ZCSpinLockProcess*/ typedef ZCSpinLock ZCCriticSect; #endif //__USE_XOPEN2K /*////////////////////////////////////////////////////////////////////////////////////// ¡á http://blog.naver.com/kimsk99?Redirect=Log&logNo=50004383787 À©µµ¿ì ÇÁ·Î±×·¥À» Çϸ鼭 ¾²·¹µå¸¦ »ý¼ºÇÒ ¶§, CreateThread¿Í _beginthread¶ó´Â µÎ ÇÔ¼ö Áß ¾î¶² ÇÔ¼ö¸¦ »ç¿ëÇØ¾ß ÇÒ Áö °í¹ÎÇÏ°Ô µÈ´Ù. ³­ Ç×»ó ¹º°¡ ±âº» API°°Àº CreateThread ¸¦ »ç¿ëÇØ ¿Ô¾ú´Ù. ±×·±µ¥ ¿À´Ã Ã¥À» Àдٰ¡ ±×°Ô À߸øµÇ¾ú´Ù´Â °ÍÀ» ¾Ë¾Ò´Ù. MSDN ¿¡ ³ª ¿Â ¼³¸íÀ» ÀÚ¼¼È÷ Àо¸é ³ª¿À´Â ³»¿ëÀ̾úÁö¸¸ º¸Åë ÀÚ¼¼È÷´Â ¾È ÀÐÀ¸´Ï ±×µ¿¾È ¸ô¶ú ¾ú´Ù. ÀÏ´Ü CreateThread ´Â À©µµ¿ì SDK¿¡¼­ Á¦°øÇÏ´Â ±âº» APIÀÌ´Ù. Ưº°ÇÑ ¶óÀ̺귯¸®¿Í ¸µÅ©ÇÏÁö ¾Ê¾Æµµ À©µµ¿ì¶ó¸é ÄÄÆÄÀÏµÇ°í µ¹¾Æ°£´Ù. ÇÏÁö¸¸ _beginthread(¶Ç´Â _beginthreadex) ´Â standard C library¿¡ ¼ÓÇÑ ÇÔ¼ö·Î ¸µÅ©ÇØ¾ß µ¿ÀÛÇÑ´Ù. ±×·¸±â ¶§¹®¿¡ ±â´É¿¡¼­µµ Â÷ÀÌ °¡ ³­´Ù. »ç½Ç ±â´É¿¡¼­ Â÷À̰¡ ³ªÁö ¾Ê´Â´Ù¸é ÀÌ·¸°Ô ±¸º°ÇÒ ÀÌÀ¯°¡ ¾ø¾úÀ» °ÍÀÌ´Ù. _beginthread ¿Í °°Àº °æ¿ì ÀÎÀÚÀÇ Á¾·ù°¡ ´Þ¶ó¼­ ¾²·¹µå »ý¼º½Ã ÇÊ¿äÇÑ ¼³Á¤À» ÇÒ ¼ö ¾ø ´Â °æ¿ì°¡ ÀÖ´Ù. ±×·¯³ª ºñ½ÁÇÑ ÇÔ¼öÀÎ _beginthreadex ´Â ¿ÏÀüÈ÷ CreateThread¿Í °°Àº ÀÎÀÚ¸¦ °¡Áö°í ÀÖ´Ù. ±×·¸±â ¶§¹®¿¡ CreateThread°¡ ¾²ÀÎ ¸ðµç °÷Àº _beginthreadex·Î Ä¡ ȯÀÌ °¡´ÉÇÏ´Ù. ³»ºÎµ¿ÀÛ¿¡¼­ °¡Àå Å« Â÷ÀÌÁ¡Àº _beginthread ´Â standard C library¿¡¼­ »ç¿ëÇÏ´Â ¿µ¿ª¿¡ ´ëÇÑ TLB ÃʱâÈ­¸¦ ÇØÁشٴ °ÍÀÌ´Ù. standary C library¿¡ ÀÖ´Â ÇÔ¼ö Áß ÀϺδ thread- safety¸¦ À§Çؼ­ TLB ¸¦ »ç¿ëÇϴµ¥ ÃʱâÈ­°¡ µÇÁö ¾Ê´Â´Ù¸é ¹®Á¦°¡ ¹ß»ýÇÒ ¼ö ÀÖ´Ù. _beginthreadex ÇÔ¼ö¸¦ »ç¿ëÇØ¼­ ¾²·¹µå¸¦ ±¸µ¿Çß´Ù¸é ½º·¹µå ÇÔ¼ö ³»¿¡¼­ ¾²·¹µå¸¦ Á¾·á Çϱâ À§Çؼ­ ExitThread ÇÔ¼ö¸¦ »ç¿ëÇϱ⠺¸´Ù´Â _endthreadex ÇÔ¼ö¸¦ »ç¿ëÇÏ±æ ±ÇÀåÇÑ´Ù. ´ëºÎºÐÀÇ °æ¿ì C library¸¦ »ç¿ëÇϱ⠶§¹®¿¡ ¾²·¹µåÀÇ »ý¼ºÀº _beginthreadex ¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù. uintptr_t _beginthreadex ( void *security, unsigned stack_size, unsigned ( *start_address )( void * ), void *arglist, unsigned initflag, unsigned *thrdaddr ); HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE AP_StartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId ); CreateThread ´Â _beginthreadex ·Î ´ëüµÉ ¼ö ÀÖ°í ±×·¡¾ß ÇÑ´Ù. dwCreationFlags [in] Flags that control the creation of the thread. If the CREATE_SUSPENDED flag is specified, the thread is created in a suspended state, and will not run until the ResumeThread function is called. If this value is zero, the thread runs immediately after creation. If the STACK_SIZE_PARAM_IS_A_RESERVATION flag is specified, the dwStackSize parameter specifies the initial reserve size of the stack. Otherwise, dwStackSize specifies the commit size. Windows 2000/NT and Windows Me/98/95: The STACK_SIZE_PARAM_IS_A_RESERVATION flag is not supported. lpThreadId [out] Pointer to a variable that receives the thread identifier. If this parameter is NULL, the thread identifier is not returned. Windows Me/98/95: This parameter may not be NULL. cf) DWORD ResumeThread( HANDLE hThread ); ¡á IN WINBASE.H typedef DWORD (WINAPI *PTHREAD_START_ROUTINE) ( LPVOID lpThreadParameter ); typedef struct _SECURITY_ATTRIBUTES { DWORD nLength; LPVOID lpSecurityDescriptor; BOOL bInheritHandle; } SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; typedef PTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE; LPTHREAD_START_ROUTINE AP_StartAddress ´Â ½ÃÀÛÇÔ¼öÆ÷ÀÎÅÍ ¿øÇüÀº DWORD WINAPI ThreadFunc(LPVOID lpRarameter) ¡á MFC ÀÇ µ¿±âÈ­ object ¾Æ·¡ object ¸¦ ¾²±â À§Çؼ­´Â °¡ ÇÊ¿ä 1) CCriticalSection cs; cs.Lock(); // ÀÛ¾÷ÄÚµå cs.Unlock(); 2) CEvent event; Thread µéÀÌ ÂüÁ¶ÇÒ ¼ö ÀÖµµ·Ï Àü¿ª ¶Ç´Â »óÀ§ ºí·°¿¡ CEvent object ¸¦ ¼±¾ðÇϰí Thread CallBack ÇÔ¼ö¿¡¼­ UINT ThreadFunc(LPVOID pParam) { while(TRUE) { CEventOvj.Lock(); // ÀáÀ̵ç´Ù. // À̺¥Æ®°¡ ¹ß»ýÇÒ ¶§ ½ÇÇàµÉ Äڵ带 Àû´Â´Ù. // ±×¸®°í ¿ÜºÎ¿¡¼­ // CEventOvj.PulseEvent(); À̳ª // CEventOvj.SetEvent(); ¸¦ È£ÃâÇÏ¸é ±ú¾î³­´Ù. // Thread °¡ Lock ÀÌ °É·Á ÀÖÁö ¾ÊÀº »óÅ¿¡¼­ // PulseEvent ÇÔ¼ö¸¦ ¸ÕÀú È£ÃâÇÏ¸é ¾Æ¹«Àϵµ ÀϾÁö ¾Ê°í // ¹Ù·Î ´ÙÀ½ ¼ø°£¿¡ Lock() ¸¦ È£ÃâÇÏ¸é ´Ù½Ã ÀáÀ» ÀÜ´Ù. // SetEvent() ÀÇ °æ¿ì¿¡´Â ±×³É Åë°úÇÑ´Ù. } //while(TRUE) } //UINT ThreadFunc(LPVOID pParam) # Window Thread Callback Type; DWORD WINAPI ThreadFunc(LPVOID lpParameter); cf) typedef unsigned long DWORD; # Linux Thread Callback Type: void* ThreadFunc()(void*) ¡á -- MFC ÀÇ µ¿±âÈ­ object //////////////////////////////////////////////////////////////////////////////////////*/ typedef pthread_t ThreadID; #define _THREAD_RETURN_ void* namespace ZNsIFace { class ZCThread_BASE { };/* class ZCThread_BASE*/ }/* namespace ZNsIFace*/ template< typename TTypeBase=ZNsMain::ZCEmpty > class ZtCThreadAttr : public TTypeBase //////// { protected: pthread_attr_t mh_ThreadAttr; public : ZtCThreadAttr() { }/* ZtCThreadAttr()*/ ZtCThreadAttr(TTypeBase& AR_CBaseType):TTypeBase(AR_CBaseType) { }/* ZtCThreadAttr(TTypeBase& AR_CBaseType)*/ template ZtCThreadAttr(const TTypeArg& AR_TTypeArg) : TTypeBase(AR_TTypeArg) { }/* template ZtCThreadAttr(const TTypeArg& AR_TTypeArg) : TTypeBase(AR_TTypeArg) */ pthread_attr_t* GetThreadAttrPtr() { return &mh_ThreadAttr ; }/* pthread_attr_t* GetThreadAttrPtr()*/ int Init() { /*//////////////////////////////////////// RETURN VALUES On success, pthread_attr_init() returns 0. On error, one of the following values is returned: ENOMEM Insufficient memory exists to create the thread attribute object. EINVAL attr does not point to writable memory. EFAULT attr is an invalid pointer ////////////////////////////////////////*/ return pthread_attr_init(&mh_ThreadAttr); }/* int Init()*/ int Fini() { return pthread_attr_destroy(&mh_ThreadAttr); }/* int Fini()*/ int GetDetachState(int& ARRI_DetachState) { return pthread_attr_getdetachstate(&mh_ThreadAttr, &ARRI_DetachState); }/* int GetDetachState(int ARRI_DetachState)*/ int SetDetachState(int AI_DetachState=PTHREAD_CREATE_DETACHED) // cf) PTHREAD_CREATE_JOINABLE { return pthread_attr_setdetachstate(&mh_ThreadAttr, AI_DetachState); }/* int SetDetachState(int AI_DetachState=PTHREAD_CREATE_DETACHED)*/ int GetSchedPolicy(int& ARRI_Policy) { return pthread_attr_getschedpolicy(&mh_ThreadAttr, &ARRI_Policy); }/* int GetSchedPolicy(int ARRI_Policy)*/ /*//////////////////////////////////////////////////////////// ¡á pthread_attr_setschedpolicy() ÀÇ 2 ¹ø Àμö¿¡ »ç¿ë°¡´ÉÇÑ °ª SCHED_FIFO First in-first out (FIFO) scheduling policy. SCHED_RR Round robin scheduling policy. SCHED_OTHER Another scheduling policy ////////////////////////////////////////////////////////////*/ int SetSchedPolicy(int AI_Policy) { return pthread_attr_setschedpolicy(&mh_ThreadAttr, AI_Policy); }/* int SetSchedPolicy(int AI_Policy)*/ int GetSchedParam(const struct sched_param& ARR_SchedParam) { // struct sched_param{int sched_priority;}; return pthread_attr_getschedparam(&mh_ThreadAttr, &ARR_SchedParam); }/* int GetSchedParam(const struct sched_param& ARR_SchedParam)*/ int SetSchedParam(const struct sched_param& AR_SchedParam) { return pthread_attr_setschedparam(&mh_ThreadAttr, &AR_SchedParam); }/* int SetSchedParam(const struct sched_param& AR_SchedParam)*/ int GetStackSize(size_t& ARRI_StackSize) { return pthread_attr_getstacksize(&mh_ThreadAttr, &ARRI_StackSize); }/* int GetStackSize(size_t& ARRI_StackSize)*/ int SetStackSize(size_t AI_StackSize) { // PTHREAD_STACK_MIN ÀÌ»óÀ̾î¾ß ÇÑ´Ù. return pthread_attr_setstacksize(&mh_ThreadAttr, AI_StackSize); }/* int SetStackSize(size_t AI_StackSize)*/ /*///////////////////////////////////////////////////////////////////////// ¡á µ¥À̺ñµå R. ºÎÆ®³ëÇÁ Àú 'POSIX ¾²·¹µå¸¦ ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹Ö' 200 page ¿¡ ½Ã½ºÅÛ¿¡¼­ _POSIX_THREAD_ATTR_STACKSIZE ±âÈ£ »ó¼ö¸¦ Á¤ÀÇÇϰí ÀÖ´Ù¸é, size_t statcksize ¼Ó¼ºÀ» »ç¿ëÇÒ ¼ö ÀÖ´Ù. °í µÇ¾î Àִµ¥, CentOS 64 bit ¿¡¼­ find /usr/include/ | xargs grep 'POSIX_THREAD_ATTR_STACKSIZE' ¸¦ ½ÇÇàÇϸé, /usr/include/bits/posix_opt.h:#define _POSIX_THREAD_ATTR_STACKSIZE 200112L À» ãÀ» ¼ö ÀÖ´Ù. -- 2011-05-23 20:44:00 ¡á ¿ª½Ã °°Àº Ã¥, °°Àº ÆäÀÌÁö¿¡ POSIX ¾²·¹µå¿¡¼­´Â ÇÑ ¾²·¹µå¿¡¼­ ¿ä±¸ÇÏ´Â ½ºÅÃÀÇ ÃÖ¼Ò Å©±â¸¦ ³ªÅ¸³»´Â ±âÈ£ »ó¼ö·Î¼­ PTHREAD_STACK_MIN À» Á¤ÀÇÇÑ´Ù. ÀÌ ±âÈ£¸¦ CentOS ¿¡¼­ ãÀ¸¸é bits/local_lim.h ¿¡ #define PTHREAD_STACK_MIN 16384 ¶ó°í µÇ¾î ÀÖ´Ù. -- 2011-05-23 20:55:00 /////////////////////////////////////////////////////////////////////////*/ public: };/* template< typename TTypeBase=ZNsMain::ZCEmpty > class ZtCThreadAttr /////////////////////////*/ template< typename TTypeBase=ZNsIFace::ZCThread_BASE > class ZtCThread : public TTypeBase /////////////////// { protected: ThreadID mh_ThreadID; public : ZtCThread() { _DEBUG_REENTRANT_CHECK_ mh_ThreadID = 0 ; } ZtCThread(TTypeBase& AR_CBaseType):TTypeBase(AR_CBaseType) { _DEBUG_REENTRANT_CHECK_ } ZtCThread(const ZtCThread& rhs):TTypeBase(rhs) { _DEBUG_REENTRANT_CHECK_ mh_ThreadID =rhs.mh_ThreadID ; (TTypeBase&)(*this)=static_cast(rhs); } template ZtCThread(const TTypeArg& AR_TTypeArg):TTypeBase(AR_TTypeArg) { _DEBUG_REENTRANT_CHECK_ } ZtCThread& operator=(const ZtCThread& rhs) { return *this; }/* ZtCThread& operator=(const ZtCThread& rhs)*/ operator ThreadID () const { return mh_ThreadID; }/* operator ThreadID () const*/ ThreadID GetThreadID() const { return mh_ThreadID; }/* ThreadID GetThreadID() const*/ bool Make(void* AP_StartAddress(void*), void* AP_Arg=NULL, pthread_attr_t* AP_ThreadAttr=NULL) { return ::pthread_create( /////////////// &mh_ThreadID , AP_ThreadAttr , AP_StartAddress , AP_Arg /*/////////*/ ) == 0 ; ///////////////// }/* bool Make(void* AP_StartAddress(void*), void* AP_Arg=NULL, pthread_attr_t* AP_ThreadAttr=NULL)*/ // ¾²·¹µå Á¾·á½Ã±îÁö ¸ÞÀÎ ÇÔ¼öÀÇ ½ÇÇàÀ» Áö¿¬(ºí·°)½ÃŲ´Ù. bool Wait() { return ::pthread_join(mh_ThreadID, NULL)==0 ; }/* bool Wait()*/ bool Wait(void** APP_ThreadReturn) { return ::pthread_join(mh_ThreadID, APP_ThreadReturn)==0 ; }/* bool Wait(void** APP_ThreadReturn)*/ static bool Wait(ThreadID AI_ThreadIDVar, void** APP_ThreadReturn) { return ::pthread_join(AI_ThreadIDVar, APP_ThreadReturn)==0 ; }/* static bool Wait(ThreadID AI_ThreadIDVar, void** APP_ThreadReturn)*/ /*//////////////////////////////////////////////////////////////////////////////////// ¡á pthread_detach ´Â ÇÁ·Î¼¼½º¿¡¼­ fork() ÈÄ¿¡ waitpid() ¸¦ ÇÏÁö ¾Ê¾Æµµ µÇµµ·Ï SIGCHILD ¸¦ ¹«½ÃÇÏ´Â °Í°ú µ¿ÀÏÇÏ´Ù. ±×¸®°í º´ÇÕ(::pthread_join) ÇÏÁö ¾ÊÀ» °Å¸é, ¹Ýµå½Ã È£ÃâÇØ¾ß ÇÏ´Â °ÍÀ¸·Î ±â¾ïÇÏÀÚ. pthread_detach() À» È£ÃâÇÏÁö ¾ÊÀ¸¸é ¾²·¹µå°¡ Á¾·áÇߴµ¥µµ ¸Þ¸ð¸®°¡ OS ¿¡ ¹ÝȯµÇÁö ¾ÊÀ» ¼ö ÀÖ´Ù. www.wordncode.com ÀÇ ÆÄÀϼ­¹ö¸¦ ¸¸µé¾î ÁÙ ¶§ ÀÌ Äڵ带 »©¸Ô¾ú´õ´Ï¸¸ Ŭ¶óÀÌ¾ðÆ®°¡ Á¾·áÇߴµ¥µµ °è¼Ó ¸Þ¸ð¸®°¡ ÁÙ¾îµéÁö ¾Ê°í Áõ°¡¸¸ ÇÏ´Â °ÍÀ̾ú´Ù. ±×·¡¼­ ¾î´À ½ÃÁ¡¿¡ (°¡»ó)¸Þ¸ð¸®¸¦ ¼ÒÁøÇÏ¿© Ŭ¶óÀÌ¾ðÆ® Á¢¼Ó½Ã¿¡ ÄÁ³Ø¼Ç ¾²·¹µå¸¦ ¸¸µéÁö ¸ø Çϰí ÀÖ¾ú´Ù! -- 2009-02-24 03:08:00 ////////////////////////////////////////////////////////////////////////////////////*/ static bool Detach(pthread_t AI_ThreadID) { return ::pthread_detach(AI_ThreadID)==0; }/* static bool Detach(pthread_t AI_ThreadID)*/ bool Detach() { return ::pthread_detach(mh_ThreadID)==0; }/* bool Detach()*/ /*////////////////////////////////////////////////////////////////////////////// ¡á ¾²·¹µå¸¦ Ãë¼Ò(pthread_cancel)ÇÑ´Ù´Â °ÍÀº ´Ù¸¥ ¾²·¹µå·ÎºÎÅÍ Ãë¼Ò¿äûÀ» ¹Þ¾Æ¼­ ÀÛµ¿À» ÁßÁöÇÏ´Â °ÍÀ» ÀǹÌÇÕ´Ï´Ù. ¸¶Ä¡ kill À» ÀÌ¿ëÇØ¼­ ÇÁ·Î¼¼½º¸¦ ÁߴܽÃŰ´Â °Í°ú ºñ½ÁÇÕ´Ï´Ù. ±×·¯³ª Áß´ÜÀ» ¿äû¹ÞÀº ¾²·¹µå°¡ ¹Ù·Î ÁߴܵǴ°¡? ±×°ÍÀº ¾Æ´Õ ´Ï´Ù. kill ·Î ÇÁ·Î¼¼½º¸¦ Á×ÀÌ´Â °Íµµ ½ÇÁ¦·Î´Â ÇÁ·Î¼¼½º¸¦ Á×ÀÌ´Â ½Ã±×³ÎÀ» º¸³» °í ±× ´ÙÀ½Àº ÇÁ·Î¼¼½º°¡ ½Ã±×³ÎÀ» ó¸®ÇÏ¿© Á×¾îÁà¾ß Çϴµ¥ °¡²û Á×Áö ¾ÊÀ» ¼öµµ Àְųª ȤÀº Áö¿¬(deferred) µÇ¾î Á×´Â °æ¿ìµµ ¹ß»ýÇÕ´Ï´Ù. ¾²·¹µåÀÇ Ãë¼Òµµ ÀÌ¿Í °°ÀÌ ¹Ù·Î Á×¾îÁÖÁö´Â ¾Ê½À´Ï´Ù. ¹°·Ð Áï½Ã Ãë¼ÒµÇµµ·Ï ¼³Á¤ÇÒ ¼öµµ ÀÖÀ¾´Ï´Ù¸¸, ¾²·¹µå Ãë¼ÒÀÇ ±âº» ¼¼ÆÃÀº Áö¿¬µÈ(deferred) Ãë¼Ò¸¦ ÀǹÌÇÕ´Ï´Ù. ¸®´ª½º ½Ã½ºÅÛ ³×Æ®¿öÅ© ÇÁ·Î±×·¡¹Ö : °¡¸ÞÃâÆÇ»ç : ±è¼±¿µ Àú 315 page ¡á cf) int pthread_setcancelstate(int state,int* oldstate) : ¿øÀÚÀû ÇÔ¼ö state Àº PTHREAD_CANCEL_ENABLE, PTHREAD_CANCEL_DISABLE ÁßÀÇ ÇÑ °ª //////////////////////////////////////////////////////////////////////////////*/ static bool Cancel(pthread_t AI_ThreadID) { return ::pthread_cancel(AI_ThreadID)==0; }/* static bool Cancel(pthread_t AI_ThreadID)*/ bool Cancel() { return ::pthread_cancel(mh_ThreadID)==0; }/* bool Cancel()*/ public: };/* template< typename TTypeBase=ZNsIFace::ZCThread_BASE > class ZtCThread ////////////////////////////////////*/ template<> class ZtCThread { protected: ThreadID mh_ThreadID; public : ZtCThread() { _DEBUG_REENTRANT_CHECK_ }/* ZtCThread()*/ ZtCThread(const ZtCThread& rhs) { mh_ThreadID=rhs.mh_ThreadID; }/* ZtCThread(const ZtCThread& rhs)*/ ZtCThread& operator=(const ZtCThread& rhs) { return *this; // nothing to do }/* ZtCThread& operator=(const ZtCThread& rhs)*/ operator ThreadID () const { return mh_ThreadID; }/* operator ThreadID () const*/ ThreadID GetThreadID() const { return mh_ThreadID; }/* ThreadID GetThreadID() const*/ bool Make(void* AP_StartAddress(void*), void* AP_Arg=NULL, pthread_attr_t* AP_ThreadAttr=NULL) { return ::pthread_create( ////////////// &mh_ThreadID , AP_ThreadAttr , AP_StartAddress , AP_Arg /*/////////*/ ) == 0 ; //////////////// }/* bool Make(void* AP_StartAddress(void*), void* AP_Arg=NULL, pthread_attr_t* AP_ThreadAttr=NULL)*/ bool Wait() { return ::pthread_join(mh_ThreadID, NULL)==0 ; }/* bool Wait()*/ bool Wait(void** APP_ThreadReturn) { return ::pthread_join(mh_ThreadID, APP_ThreadReturn)==0 ; }/* bool Wait(void** APP_ThreadReturn)*/ static bool Wait(ThreadID AI_ThreadIDVar, void** APP_ThreadReturn) { return ::pthread_join(AI_ThreadIDVar, APP_ThreadReturn)==0 ; }/* static bool Wait(ThreadID AI_ThreadIDVar, void** APP_ThreadReturn)*/ static bool Detach(pthread_t AI_ThreadID) { return ::pthread_detach(AI_ThreadID)==0; }/* static bool Detach(pthread_t AI_ThreadID)*/ bool Detach() { return ::pthread_detach(mh_ThreadID)==0; }/* bool Detach()*/ static bool Cancel(pthread_t AI_ThreadID) { return ::pthread_cancel(AI_ThreadID)==0; }/* static bool Cancel(pthread_t AI_ThreadID)*/ bool Cancel() { return ::pthread_cancel(mh_ThreadID)==0; }/* bool Cancel()*/ public: };/* template<> class ZtCThread*/ /*////////////////////////////////////////////////////////////////////////////////////// ¡á class ZtCMutexCond ´Â window ¿¡´Â ¾ø´Â ¸®´ª½º ¹ÂÅØ½º Á¶°Çº¯¼ö Ŭ·¡½º À̰ÍÀÌ À¯¿ëÇÑ °æ¿ì´Â ´Ù¼öÀÇ ¾²·¹µå°¡ ÇÔ¼ö A, ÇÔ¼ö B, ÇÔ¼ö C ¸¦ ¼öÇàÇϴµ¥, ¹Ýµå½Ã ÇÔ ¼ö A -> B -> C ÀÌ ¼ø¼­·Î ½ÇÇàÇØ¾ß ÇÏ°í °¢ ÇÔ¼ö´Â µ¿±âÈ­¸¦ ÇØÁÖ¾î¾ß ÇÒ ¶§, ¾²·¹µå Á¶ °Çº¯¼ö¸¦ »ç¿ëÇϸé ÇÑ °³ÀÇ ¹ÂÅØ½º·Î °¡´ÉÇϳª (Á¶°Çº¯¼ö´Â 3-1 °³), ¹ÂÅØ½º·Î¸¸ ÇÑ´Ù¸é A, B,C ¿ë °¢°¢ 3 °³ÀÇ ¹ÂÅØ½º¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù. Áï ÇÑ °³ÀÇ ¹ÂÅØ½º¿¡ ¿©·¯ °³ÀÇ Á¶°Ç º¯¼ö°¡ ´ëÀÀÇÒ ¼ö ÀÖ´Ù. ¹Ý´ë·Î ÇÑ °³ÀÇ Á¶°Çº¯¼ö¿¡ ¿©·¯°³ÀÇ ¹ÂÅØ½º°¡ ´ëÀÀÇÒ ¼ö´Â ¾ø´Ù. Á¶°Çº¯¼ö´Â º¹»ç»ç¿ëÇØ¼­´Â ¾ÈµÈ´Ù. µû¶ó¼­ º¹»ç»ý¼ºÀÚ¿Í ´ëÀÔ¿¬»êÀÚÀÇ ½ÇÇàÀ» ¸·´Â´Ù. Á¶°Çº¯¼ö´Â ¹Ýµå½Ã Çѹø¸¸ ÃʱâÈ­ µÇ¾î¾ß ÇÑ´Ù. ¡á ¾î¶² ÀÛ¾÷ Å¥¿¡ ´Ù¼öÀÇ ¾²·¹µå°¡ Á¢±ÙÇÏ¿© ÀÛ¾÷À» °¡Á®¿Â´Ù°í °¡Á¤ÇÏÀÚ. ÀÛ¾÷Å¥¿¡ Á¢±ÙÇÏ´Â ¾²·¹µå´Â, Å¥¿¡ Á¢±ÙÇÏ´Â µ¿¾ÈÀº ´Ù¸¥ ¾²·¹µå°¡ µ¿½Ã Á¢±ÙÇÏÁö ¾Êµµ·Ï 'ÀÛ¾÷ Å¥ Á¢±Ù µ¿±â È­ object ' ¿¡ lock À» °É°í ÇØ´ç Å¥°¡ ºñ¾îÀÖ´ÂÁö ±×·¸Áö ¾ÊÀºÁö¸¦ Á¶»çÇÒ °ÍÀÌ´Ù. À̶§ Å¥¿¡ µî·ÏµÈ ÀÛ¾÷ÀÌ Çϳª¶óµµ ÀÖ´Ù¸é ±× ÀÛ¾÷À» °¡Á®¿À°í 'ÀÛ¾÷Å¥ Á¢±Ù µ¿±âÈ­ object' ¸¦ unlock ÇÒ °ÍÀÌ´Ù. ¸¸ÀÏ Å¥¿¡ µî·ÏµÈ ÀÛ¾÷ÀÌ ¾ø´Ù¸é 'ÀÛ¾÷ Å¥ Á¢±Ù µ¿±âÈ­ object' ¸¦ unlock Çϰí ÀÚ½ÅÀº ÀÛ¾÷Å¥¿¡ ÀÛ¾÷ÀÌ µî·ÏµÉ ¶§±îÁö ºí·°µÇ¾î¾ß ÇÑ´Ù. À̶§ ÀÚ½ÅÀÌ ºí·°µÇ°í ÀÖ´Ù ´Â °ÍÀ» ¾Ë¸®´Â Ç¥½Ã¸¦ Çϰí(±×·¡¾ß ³ªÁß¿¡ '±ú¿ï' ¼ö ÀÖÀ¸´Ï±î) ºí·°µÇ¾ß Çϴµ¥, ÀÌ »çÀÌ ¿¡ Áï unlock °ú ºí·°Ç¥½Ã¸¦ ÇÏ°í ºí·°µÇ´Â »çÀÌ¿¡ ´Ù¸¥ ¾²·¹µå°¡ ³¢¾îµé¾î 'ÀÛ¾÷Å¥ Á¢±Ù µ¿±âÈ­ object' ¿¡ lock À» °É°í ÀÛ¾÷À» µî·ÏÇϸé, ÀÛ¾÷Àº ºÐ¸í Àִµ¥ ºí·°Ç¥½Ã¸¦ ÇÏ·Á´Â ¾²·¹µå´Â ºí·°Ç¥½Ã¸¦ Çϱ⵵ ÀüÀ̹ǷÎ, ´Ù¸¥ ¾²·¹µå´Â ±× ¾²·¹µå°¡ ºí·°µÇ°í ÀÖÁö ¾Ê´Ù°í º¸°í º° 󸮾øÀÌ 'ÀÛ¾÷Å¥ Á¢±Ù µ¿±âÈ­ object' ¿¡ unlock À» ÇÏ°í ´ÙÀ½À» ÁøÇàÇÒ °ÍÀÌ´Ù. ±×·¯¸é ºí·°Ç¥½Ã¸¦ÇÏ°í ºí·°µÇ·Á´Â ¾²·¹µå´Â ºí·°ÀÌ ÇØÁ¦µÉ ±âȸ¸¦ °®Áö ¸øÇÑ Ã¤ ¿µ¿øÈ÷ ºí ·°µÉ ¼ö ÀÖ´Ù. ÀÌ »çŸ¦ ¹æÀÚÇϱâ À§ÇØ 'ÀÛ¾÷Å¥ Á¢±Ù µ¿±âÈ­ object' ¿¡ unlock À» ÇÏ´Â ÀÛ¾÷°ú ºí·°»óÅ·ΠÁøÀÔÇÏ´Â ¸í·ÉÀº ¿øÀÚÀûÀ¸·Î ÀÌ·ç¾îÁ®¾ß ÇÑ´Ù. ÀÌ·¯¸é ´Ù¸¥ ¾²·¹µå°¡ ºí ·°µÇ°í ÀÖ´Â ¾²·¹µå¸¦ Á¤È®ÇÏ°Ô ÆÇº°ÇÒ ¼ö ÀÖ°Ô²û º¸ÀåÇØÁØ´Ù. À̰ÍÀÌ Á¶°Ç º¯¼ö°¡ Á¸ÀçÇÏ ´Â ÀÌÀ¯ÀÌ´Ù. Á¶°Ç º¯¼ö ´ë±â´Â Ç×»ó ¹ÂÅØ½º¸¦ Àá±Ù ä·Î ¸®ÅÏÇØ¾ß ÇÑ´Ù. (¹°·Ð ¸®ÅÏÇϱâ Àü, ´ë±âÇϰí ÀÖÀ» µ¿¾ÈÀº ¹ÂÅØ½º¸¦ Àá±×Áö ¾ÊÀº »óÅ´Ù.) ¡á ¹ÂÅØ½º¸¦ Àá±×Áö ¾ÊÀº ä·Î ¾ó¸¶µçÁö Á¶°Çº¯¼ö·Î ½Ã±×³ÎÀ» º¸³»°Å³ª ºê·Îµåij½ºÆ® ÇÒ ¼ö ÀÖ ´Ù. ¾î¶² ¾²·¹µå°¡ Á¶°Çº¯¼ö·Î ½Ã±×³ÎÀ» º¸³»°Å³ª ºê·Îµåij½ºÆ®ÇÑ´Ù ÇÒÁö¶óµµ ´ë»ó Á¶°Ç º¯ ¼ö¿¡¼­ ´ë±â ÁßÀÎ ¾²·¹µå°¡ Çϳªµµ ¾ø´Ù¸é ¾Æ¹«Àϵµ ÀϾÁö ¾Ê´Â´Ù. Àá½Ã ÈÄ ´Ù¸¥ ¾²·¹µå °¡ pthread_cond_wait() ÇÔ¼ö¸¦ È£ÃâÇÑ´Ù¸é, ¹Ù·Î Àü¿¡ ÇØ´ç Á¶°Ç º¯¼ö·Î ½Ã±×³ÎÀÌ º¸³»Á³ ´Ù´Â °ÍÀ» ¾ËÁö ¸øÇÏ°í ±×Àú ±â´Ù¸®´Â ¼ö¹Û¿¡ ¾ø´Ù. µû¶ó¼­ ÀÌ ½ÃÁ¡ÀÌ Àý´ë·Î ±â´Ù·Á¼­´Â ¾ÈµÇ´Â »óȲÀ̶ó¸é ¾²·¹µå´Â °áÄÚ ±ú¾î³¯ ¼ö ¾ø°Ô µÈ´Ù. ¾²·¹µå°¡ Á¶°Çº¯¼ö¿¡¼­ ºí·°µÉ ¶§ ±îÁö ¹ÂÅØ½º´Â Àá±ä ä·Î ³²¾Æ Àֱ⠶§¹®¿¡, ¼ú¾î °Ë»ç¿Í ´ë±âµµÁß¿¡´Â(´Ù¸¥ ¾²·¹µåµé¿¡ ÀÇ ÇØ) ¼ú¾î°¡ ¼³Á¤µÉ ¼ö ¾ø´Ù. Áï ¹ÂÅØ½º°¡ Àá°Ü ÀÖÀ¸¹Ç·Î ´Ù¸¥ ¾²·¹µåµéÀÌ ¼ú¾î µîÀÇ °øÀ¯ µ¥ÀÌŸµéÀ» º¯°æÇÒ ¼ö ¾ø´Â °ÍÀÌ´Ù. ¡á Ç×»ó ¼ú¾î¸¦ Å×½ºÆ®Ç϶ó! ±×¸®°í ´Ù½Ã Çѹø Å×½ºÆ®Ç϶ó! ¾²·¹µå°¡ ±ú¾î³µÀ» ¶§, ´Ù½Ã ¼ú¾î¸¦ Å×½ºÆ®ÇÏ´Â °Í ¿ª½Ã ¸Å¿ì Áß¿äÇÏ´Ù. µû¶ó¼­ Á¶°Ç º¯¼ö ´ë±â´Â Ç×»ó ·çÇÁ¸¦ ÀÌ¿ëÇÏ¿© ¼öÇàÇÏ´Â °ÍÀÌ ÁÁ´Ù. -- µ¥À̺ñµå R ºÎÆ®³ëÇÁ Àú Posix ¾²·¹µå¸¦ ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹Ö 123P °¢ Á¶°Çº¯¼ö´Â ƯÁ¤ ¹ÂÅØ½º ¹× ¼ú¾î Á¶°Ç°ú °áÇյǾî¾ß ÇÑ´Ù. ¶ÇÇÑ ¾²·¹µå°¡ Á¶°Ç º¯¼ö»ó ¿¡¼­ ´ë±âÇÒ ¶§´Â Ç×»ó °áÇÕµÈ ¹ÂÅØ½º¸¦ Àá±×°í ÀÖ¾î¾ß ÇÑ´Ù. Á¶°Çº¯¼ö ´ë±â¸í·ÉÀ» »ç¿ëÇÏ ¸é, ¾²·¹µå¸¦ ºí·ÏÇϱâ Àü¿¡ ¹ÂÅØ½ºÀÇ Àá±ÝÀ» ÇØÁ¦ÇÏ°í ¿ø·¡ ÄÚµå·Î ¸®ÅÏÇϱâ Àü¿¡ ¹ÂÅØ½º ¸¦ ´Ù½Ã Àá±Ù´Ù´Â »ç½ÇÀ» ±â¾ïÇÏÀÚ -- µ¥À̺ñµå R ºÎÆ®³ëÇÁ Àú Posix ¾²·¹µå¸¦ ÀÌ¿ëÇÑ ÇÁ·Î±×·¡¹Ö 123P ¡á window ¿¡¼­´Â ¹ÂÅØ½º Á¶°Ç º¯¼ö¸¦ ±¸ÇöÇϱⰡ ´ë´ÜÈ÷ Èûµçµ¥, ¸¸ÀÏ Á¶°Ç º¯¼öÀÇ ±â´ÉÀ» ƯÁ¤ ¾²·¹µåÀÇ "´ë±â"¿Í "±ú¾î³²" À¸·Î ÇÑÁ¤ÇÑ´Ù¸é IOCP ¿Í GetQueuedCompletionStatus() ÇÔ¼ö¸¦ ÀÌ¿ëÇÏ¿© ±¸ÇöÇÒ ¼ö ÀÖ´Ù. window ¿¡¼­ Á¶°Çº¯¼ö´Â À̺¥Æ®·Î ±¸ÇöÇÏ´Â °ÍÀÌ Á¦ÀÏ ¹«³­ÇÑ °Í °°´Ù. -- 2008-12-05 15:06:00 ¡á ÀÌÁ¦ »ý°¢Çغ¸´Ï Á¶°Çº¯¼öÀÇ Áß¿ä ¿ªÇÒÀº ù° "´ë±â" ¿Í µÑ° ¹ÂÅØ½º¸¦ Àá±Ù ¾²·¹µå°¡ ¾Æ ´Ñ "´Ù¸¥ ¾²·¹µå°¡ Àá±ÝÀ» ÇØÁ¦ÇÏ´Â °Í" À» Çã¿ëÇÏ´Â °ÍÀÌ ¾Æ´Ò±î ÇÑ´Ù. -- 2007-11-12 07:56:00 ¡á "ÀÛ¾÷¾²·¹µå" °¡ Á¶°Çº¯¼ö¿¡¼­ ´ë±âÇϰí ÀÖ°í, "ÁÖ¾²·¹µå" ¿¡¼­ "ÀÛ¾÷¾²·¹µå" ¿¡ ½Ã±×³ÎÀ» º¸³» ±ú¿ì´Â °úÁ¤À» »ý°¢Çغ¸ÀÚ. "ÁÖ¾²·¹µå" ¿¡¼­ "ÀÛ¾÷¾²·¹µå" ¿¡ ½Ã±×³ÎÀ» º¸³»¸é, "ÀÛ¾÷ ¾²·¹µå" ´Â ¹ÂÅØ½º¿¡ Lock À» °É°í ´ë±â ÇÔ¼ö¸¦ ºüÁ®³ª¿Ã·Á°í ÇÒ °ÍÀÌ´Ù. À̶§ "ÁÖ¾²·¹µå" ¿¡¼­ Lock À» °É°í ½Ã±×³ÎÀ» º¸³Â´Ù¸é, "ÀÛ¾÷¾²·¹µå" ´Â ´ë±â ÇÔ¼ö¸¦ ¸®ÅÏÇϱâ Àü¿¡ ÀÌ¹Ì ¹ÂÅØ½º°¡ Àá°ÜÀÖÀ¸¹Ç·Î, ¹ÂÅØ½º°¡ Ç®¸± ¶§±îÁö ´Ù½Ã ´ë±âÇÏ°Ô µÈ´Ù. µû¶ó¼­ ½Ã±×³ÎÀ» º¸³½ "ÁÖ¾²·¹µå" ´Â °¡±ÞÀû »¡¸® Lock À» Ç®¾îÁÖ¾î¾ß ÇÑ´Ù. ¶ÇÇÑ ½Ã±×³Î·Î ÀÎÇØ ±ú¾î³­ "ÀÛ¾÷¾² ·¹µå"µµ ¹ÂÅØ½º¿¡ Lock À» °É°í ´ë±â ÇÔ¼ö¸¦ ¸®ÅÏÇÏ°Ô µÇ¸é ¹ÂÅØ½ºÀÇ Lock À» »¡¸® Ç®¾îÁÖ ´Â °ÍÀÌ ÁÁ´Ù. -- 2007-11-16 05:51:00 //////////////////////////////////////////////////////////////////////////////////////*/ template< typename TData=ZNsMain::ZCEmpty ///////////// > class ZtCMutexCond : public TData, ZNsMain::ZCNonCopyable { protected: ::pthread_cond_t mh_PThread_Cond; public : ::pthread_cond_t GetHandle() const { return mh_PThread_Cond; }/* ::pthread_cond_t GetHandle() const*/ int InitCond(pthread_condattr_t* AP_CondAttr=NULL) { return ::pthread_cond_init(&mh_PThread_Cond, AP_CondAttr) ; /*///////////////////////////////////////////////////////// ¡á pthread_cond_init ÀÇ ¿¡·¯ ¹Ýȯ°ª(¼º°ø½Ã 0) EAGIN (¸Þ¸ð¸®ÀÌ¿ÜÀÇ) ÀÚ¿øÀÌ ºÎÁ·ÇÏ´Ù. ENOMEM ¸Þ¸ð¸®°¡ ºÎÁ·ÇÏ´Ù. EBUSY Á¶°Çº¯¼ö°¡ ÀÌ¹Ì ÃʱâÈ­ µÇ¾î ÀÖ´Ù. EINVAL AP_CondAttr ÀÌ ¿Ã¹Ù¸£Áö ¾Ê´Ù. °¡±ÞÀûÀ̸é Á¤ÀûÃʱâÈ­¸¦ »ç¿ëÇÑ´Ù. (PTHREAD_COND_INITIALIZER) /////////////////////////////////////////////////////////*/ }/* int Init(pthread_condattr_t* AP_CondAttr=NULL)*/ int FiniCond() { /*//////////////////////////////////////////////////////////// ¡á pthread_cond_destroy() RETURN VALUES On success, pthread_cond_destroy() returns 0. On error, one of the following values is returned: EINVAL cond does not refer to an initialized condition variable. EBUSY The condition variable is in use by another thread (for example, in a condition wait). EFAULT cond is an invalid pointer ¡á PTHREAD_COND_INITIALIZER ¸ÞÅ©·Î¸¦ »ç¿ëÇÏ¿© Á¤ÀûÀ¸·Î ÃʱâÈ­µÈ Á¶°Çº¯¼ö´Â ÆÄ±«ÇÏÁö ¾Ê¾Æµµ µÈ´Ù. ////////////////////////////////////////////////////////////*/ return ::pthread_cond_destroy(&mh_PThread_Cond) ; }/* int FiniCond()*/ int WaitCond(pthread_mutex_t& AR_MutexArg) { return ::pthread_cond_wait(&mh_PThread_Cond, &AR_MutexArg) ; /*////////////////////////////////////////////////////////// ¡á pthread_cond_wait ÇÔ¼ö°¡ Á¦´ë·Î ¼öÇàµÇ·Á¸é ¹ÂÅØ½º°¡ Ãʱâ È­µÇ¾î ÀÖ°í lock ÀÌ µÇ¾î ÀÖ¾î¾ß ÇÑ´Ù. ÀÌ ÇÔ¼ö°¡ ½ÇÇàµÇ¸é ÇÔ¼ö´Â ³»ºÎ¿¡ »ç¿ëµÈ ¹ÂÅØ½ºÀÇ lock À» ÇØÁ¦ÇÑ Ã¤·Î ´ë±â ÀÛ ¾÷¿¡ µé¾î°£´Ù. ±×¸®°í Á¶°Ç º¯¼ö¿¡ ´ëÇÑ ½Ã±×³ÎÀÌ °ËÃâµÇ¸é ÀÛ¾÷À» Àç°³ÇÑ´Ù. Áï ÇØ´çÁ¶°Ç º¯¼ö¿¡ ´ëÇÑ ½Ã±×³ÎÀÌ ¹ß»ýÇÏ ¸é ³»ºÎÀÇ Àμö·Î ÁöÁ¤µÈ ¹ÂÅØ½º¸¦ Àá±ÙÈÄ pthread_cond_wait ÇÔ¼öÀÇ ´ÙÀ½ ¶óÀÎÀ» ½ÇÇàÇÏ°Ô µÈ´Ù. pthread_cond_timedwait ÇÔ¼ö¸¦ »ç¿ëÇϸé timespec ¿¡ ÁöÁ¤µÈ ½Ã°£¸¸Å­ ´ë±â¸¦ ÇÏ°Ô µÈ´Ù. ¸¸¾à ÁöÁ¤µÈ ½Ã°£³»¿¡ ½Ã±×³ÎÀÌ °ËÃâµÇÁö ¾ÊÀ¸¸é ŸÀÓ ¾Æ¿ô ¿¡·¯ÄÚµå¿Í ÇÔ²² ½ÇÇàÀÌ ÁßÁöµÈ´Ù. //////////////////////////////////////////////////////////*/ }/* int WaitCond(pthread_mutex_t& AR_MutexArg)*/ int WaitCondTime(pthread_mutex_t& AR_MutexArg, struct timespec& AR_Expriation) { // time out À̸é ZNsEnum::ZEThread_TimeOut(ETIMEDOUT) À» ¹ÝȯÇÑ´Ù. return ::pthread_cond_timedwait(&mh_PThread_Cond, &AR_MutexArg, &AR_Expriation) ; /*///////////////////////////////////////////////////// DESCRIPTION The pthread_cond_timedwait() function blocks on the specified condition variable, which atomically releases the specified mutex and causes the calling thread to block on the condition variable The blocked thread may be awakened by a call to pthread_cond_signal() or pthread_cond_broadcast(), or if the time specified by abstime is reached. This function atomically releases the mutex, causing the calling thread to block on the condition variable Upon successful completion, the mutex is locked and owned by the calling thread. pthread_cond_timedwait() is the same as pthread_cond_wait(), except an error is returned if the system time equals or exceeds the time specified by abstime before the condition variable is signaled or broadcast, or if the absolute time specified by abstime has already passed at the time of the call. When timeouts occur, pthread_cond_timedwait() releases and reacquires the mutex. When using condition variables, there should always be a boolean predicate involving shared variables related to each condition wait. This predicate should become true only when the thread should proceed. Because the return from pthread_cond_timedwait() does not indicate anything about the value of this predicate, the predicate should be reevaluated on return. Unwanted wakeups from pthread_cond_timedwait() may occur (since another thread could have obtained the mutex, changed the state and released the mutex, prior to this thread obtaining the mutex); the reevaluation of the predicate ensures consistency. The pthread_cond_timedwait() function is a cancellation point. If a cancellation request is acted on while in a condition wait when the cancellation type of a thread is set to deferred, the mutex is reacquired before calling the first cancellation cleanup handler. In other words, the thread is unblocked, allowed to execute up to the point of returning from the call pthread_cond_timedwait(), but instead of returning to the caller, it performs the thread cancellation. -------------------------------------------------------------------------------- PARAMETERS cond Is the condition variable to wait on. mutex Is the mutex associated with the condition variable. abstime Is the absolute time at which the wait is cancelled if not signaled or broadcast. -------------------------------------------------------------------------------- RETURN VALUES On success, pthread_cond_timedwait() returns 0. On error, one of the following values is returned: EINVAL cond does not refer to an initialized condition variable, or mutex does not refer to an initialized mutex. Different mutexes were specified in multiple waits on cond. mutex is not owned by the caller. EFAULT cond, mutex, or abstime is an invalid pointer. ETIMEDOUT The specified absolute time has passed. -------------------------------------------------------------------------------- CONFORMANCE POSIX P1003.1 (1996) -------------------------------------------------------------------------------- MULTITHREAD SAFETY LEVEL MT-safe. ///////////////////////////////////////////////////////////////////////////////*/ }/* int WaitCondTime(pthread_mutex_t& AR_MutexArg, struct timespec& AR_Expriation)*/ int WakeCond() { return ::pthread_cond_signal(&mh_PThread_Cond); }/* int WakeCond()*/ /*/////////////////////////////////////////////////////////////////////////////// ¡á pthread_cond_broadcast() ÇÔ¼ö´Â Á¶°Ç º¯¼ö¿¡¼­ ´ë±âÇÏ´Â ¸ðµç ¾²·¹µå¿¡°Ô ½Ã±×³Î À» º¸³½´Ù. ¸ðµç ¾²·¹µå°¡ ÀϾ°Ô µÇ¹Ç·Î ´ë°³ °æÇÕÀÌ ¹ß»ýÇÒ °¡´É¼ºÀÌ ÀÖ´Ù. ¸¸ ÀÏ ÇØ¾ß ÇÒ ÀÛ¾÷ÀÌ 10 °³¶ó¸é ½ÇÁ¦·Î ÀÏÀ» °¡Á®°¡´Â ¾²·¹µå´Â 1 °³ÀÏ Å×°í ³ª¸ÓÁö´Â Á¶°ÇÀ» ºñ±³ÇÑ µÚ¿¡ ´Ù½Ã ´ë±âÇÑ´Ù. ÀÌ·¸°Ô ¾µµ¥¾øÀÌ ±ú¾î³­ ¾²·¹µåµéÀÌ ´Ù½Ã ´ë±â »óÅ·Π°¡´Â °ÍÀº ÇÊ¿¬ÀûÀ¸·Î ¿À¹öÇìµå¸¦ ¹ß»ý½ÃŰ°Ô µÈ´Ù. µû¶ó¼­ ¾î¶² °æ¿ì¿¡ ºê ·Îµåij½ºÆ®¸¦ ¾µ °ÍÀÎÁö¸¦ Àß »ý°¢Çؼ­ µðÀÚÀÎÇØ¾ß ÇÑ´Ù. -- ¸®´ª½º ½Ã½ºÅÛ ³×Æ®¿öÅ© ÇÁ·Î±×·¡¹Ö, ±è¼±¿µ Àú, °¡¸ÞÃâÆÇ»ç ///////////////////////////////////////////////////////////////////////////////*/ int BoradCast() { return ::pthread_cond_broadcast(&mh_PThread_Cond) ; }/* int BoradCast()*/ public: };/* template< typename TData=ZNsMain::ZCEmpty > class ZtCMutexCond //////////////////////*/ /*/////////////////////////////////////////////////////////////// ¡á mutex ¿Í Á¶°Çº¯¼ö¸¦ °áÇÕÇÑ Å¬·¡½º´Ù. ZtCMutexCond<> ÅÛÇø´°ú ZCProcessMutex µîÀ» ÀûÀýÈ÷ ÀÌ¿ëÇÏ¸é µÇÁö¸¸ Á»´õ ÃÖÀûÈ­ Çϱâ À§ ÇØ¼­ º°µµ·Î ±¸ÇöÇÏ´Â °ÍÀÌ´Ù. ///////////////////////////////////////////////////////////////*/ template< typename TData=ZNsMain::ZCEmpty > class ZtCMutexCondData : public TData { protected: pthread_mutex_t mh_Mutex; pthread_cond_t mh_Cond ; public : int InitCond(const pthread_mutexattr_t* AP_MutexAttr=0, const pthread_condattr_t* AP_CondAttr=0) { #if(_CODE_OLD_) // ½ÇÇè¿ë ÄÚµå. bool VB_IsOK1=::pthread_mutex_init(&mh_Mutex, AP_MutexAttr)==ZNsMain::ZNsEnum::ZEThread_OK; bool VB_IsOK2=::pthread_cond_init (&mh_Cond, AP_CondAttr )==ZNsMain::ZNsEnum::ZEThread_OK; return (VB_IsOK1 && VB_IsOK2) ? ZNsMain::ZNsEnum::ZEThread_OK : ZNsMain::ZNsEnum::ZEThread_Invalid ; #else return ( ::pthread_mutex_init(&mh_Mutex, AP_MutexAttr)==ZNsMain::ZNsEnum::ZEThread_OK && ::pthread_cond_init (&mh_Cond, AP_CondAttr )==ZNsMain::ZNsEnum::ZEThread_OK /*///*/ ) ? ZNsMain::ZNsEnum::ZEThread_OK : ZNsMain::ZNsEnum::ZEThread_Invalid ; #endif }/* int Init(const pthread_mutexattr_t* AP_MutexAttr=0, const pthread_condattr_t* AP_CondAttr=0)*/ int Lock() { return ::pthread_mutex_lock(&mh_Mutex); }/* bool Lock()*/ int TryLock(const timespec* AP_TimeOut) { return ::pthread_mutex_trylock(&mh_Mutex); }/* int TryLock(const timespec* AP_TimeOut)*/ int UnLock() { return ::pthread_mutex_unlock(&mh_Mutex); }/* int UnLock()*/ int WaitCond() // ÇØ´ç ¹ÂÅØ½º¿¡ lock ÀÌ °É·Á ÀÖ¾î¾ß ÇÑ´Ù. { return ::pthread_cond_wait(&mh_Cond, &mh_Mutex) ; }/* int WaitCond()*/ #ifdef __USE_XOPEN2K int Lock(const timespec* AP_TimeOut) { return ::pthread_mutex_timedlock(&mh_Mutex, AP_TimeOut); }/* int Lock(const timespec* AP_TimeOut)*/ int WaitCondTime(const timespec* AP_TimeOut) { return ::pthread_cond_timedwait(&mh_Cond, &mh_Mutex, AP_TimeOut) ; }/* int WaitCondTime(const timespec* AP_TimeOut)*/ int WaitCondTime(int AI_TimeOutMili) { timespec VO_TimeAbs; // Àý´ë½Ã°£ timeval VO_TimeNow; /*/////////////////////////////////////////////////////// ¡á timespec struct timespec { __time_t tv_sec ; // Seconds. long int tv_nsec; // Nanoseconds. 10 ¾ïºÐÀÇ 1 ÃÊ, 1 ¹Ð¸®ÃÊ=1000*1000 ³ª³ëÃÊ }; ¡á int gettimeofday( struct timeval *tv, struct timezone *tz); int settimeofday(const struct timeval *tv,const struct timezone *tz); -- linux manual ¿¡¼­ struct timeval { long tv_sec; // ÃÊ long tv_usec; // ¸¶ÀÌÅ©·ÎÃÊ }; struct timezone { int tz_minuteswest; // ±×¸®´ÏÄ¡ ¼­Ãø ºÐÂ÷(minutes) int tz_dsttime; // DST º¸Á¤ ŸÀÔ }; timezone struct ´Â »ç¿ëÇÏÁö ¾Ê´Â´Ù; ¸®´ª½º¿¡¼­ tz_dsttime Çʵ尡 »ç¿ëµÇÁö ¾Ê´Â´Ù. Áö±Ý±îÁö ±×·¸°í ¾ÕÀ¸·Îµµ libc ³ª glibc¿¡¼­ Áö¿øµÇÁö ¾ÊÀ» °ÍÀÌ´Ù. Ä¿³Î ¼Ò½º¿¡¼­(¼±¾ð À̿ܿ¡) ÀÌ Çʵ尡 ³ª¿À´Â ¸ðµç °æ¿ì´Â ¹ö±×ÀÌ´Ù. ±×·¡¼­ ´ÙÀ½ ³»¿ëÀº ¼øÀüÈ÷ ¿ª»çÀûÀÎ Èï¹Ì°Å¸®´Ù. ~~~~~~ gettimeofday¿Í settimeofday ¸ðµÎ ¼º°øÇϸé 0À» ¸®ÅÏÇϸç, ½ÇÆÐ½Ã¿¡´Â -1À» ¸®ÅÏÇÑ´Ù.(errno´Â Àû´çÇÑ °ªÀ¸·Î ¼³Á¤µÈ´Ù.) ///////////////////////////////////////////////////////*/ ::gettimeofday(&VO_TimeNow, NULL); VO_TimeAbs.tv_sec =VO_TimeNow.tv_sec + (AI_TimeOutMili/1000) ; VO_TimeAbs.tv_nsec=VO_TimeNow.tv_usec*1000 + (AI_TimeOutMili%1000)*1000*1000 ; return ::pthread_cond_timedwait(&mh_Cond, &mh_Mutex, &VO_TimeAbs) ; // return ZEThread_TimeOut if timeout }/* int WaitCondTime(int AI_TimeOutMili)*/ #endif //__USE_XOPEN2K int WakeCond() { return ::pthread_cond_signal(&mh_Cond); }/* int WakeCond()*/ int WakeAllCond() { return ::pthread_cond_broadcast(&mh_Cond); }/* int WakeAllCond()*/ int BroadCast() { return WakeAllCond(); }/* int BroadCast()*/ int FiniCond() { #if(_CODE_OLD_) // ½ÇÇè¿ë ÄÚµå. bool VB_IsOK1=::pthread_cond_destroy (&mh_Cond )==ZNsMain::ZNsEnum::ZEThread_OK; bool VB_IsOK2=::pthread_mutex_destroy(&mh_Mutex)==ZNsMain::ZNsEnum::ZEThread_OK; return (VB_IsOK1 && VB_IsOK2) ? ZNsMain::ZNsEnum::ZEThread_OK : ZNsMain::ZNsEnum::ZEThread_Invalid ; #else return ( ::pthread_cond_destroy (&mh_Cond )==ZNsMain::ZNsEnum::ZEThread_OK && ::pthread_mutex_destroy(&mh_Mutex)==ZNsMain::ZNsEnum::ZEThread_OK /*///*/ ) ? ZNsMain::ZNsEnum::ZEThread_OK : ZNsMain::ZNsEnum::ZEThread_Invalid ; #endif }/* int FiniCond()*/ public: };/* template< typename TData=ZNsMain::ZCEmpty > class ZtCMutexCondData : public TData ///*/ /*////////////////////////////////////////////////////////////////// ¡á ZtCEventCond<> ÅÛÇø´Àº Window ÀÇ event ¿Í °°ÀÌ, ƯÁ¤ Á¶°Ç¿¡¼­ ´ë ±âÇÏ´Â ¸ðµç ¾²·¹µå¸¦ ÇѲ¨¹ø¿¡ ±ú¿ì±â À§Çؼ­ ÇÊ¿äÇÏ´Ù. Linux ÀÇ pthread_cond_signal() ÇÔ¼ö´Â ÇØ´ç Á¶°Ç º¯¼ö¿¡ ´ë±âÇϰí ÀÖ´Â ¾²·¹µå Áß Çϳª¸¦ ±ú¿î´Ù. event È¿°ú¸¦ ³¾·Á¸é pthread_cond_broadcast() ¸¦ »ç¿ëÇØ¾ß ÇÑ´Ù. ´Ü¼øÈ÷ WakeCond() ÇÔ¼ö¸¦ WakeAllCond() ÇÔ¼ö·Î °¡¸®°í ÀÖ´Ù. -- 2009-10-25 23:05:00 ¡á Á¶°Ç º¯¼ö¿¡¼­ ´Ù¼öÀÇ ¾²·¹µå°¡ ´ë±âÇϰí Àִµ¥, signal À» 2 ȸ ¿¬¼Ó À¸·Î º¸³½ °æ¿ì¿¡, 2 °³ ¾²·¹µå°¡ ¿¬¼ÓÀûÀ¸·Î ±ú¾î³­´Ù°í º¸ÀåÇÒ ¼ö ¾ø ´Ù. signal 1 ȸ ¹ß»ý½Ã¿¡ context switching ÀÌ ÀϾ¼­ ±ú¾î³­ ¾²·¹ µå°¡ ¹«½¼ ÀÏÀ» ÇÑ ´ÙÀ½¿¡, ´Ù½Ã Á¶°Ç º¯¼ö¿¡¼­ ´ë±âÇÑ´Ù¸é, 2 ¹øÂ° signal ¿¡¼­ ±× ¾²·¹µå°¡ ¶Ç ±ú¾î³¯ ¼ö ÀÖ´Â °ÍÀÌ´Ù. -- 2009-10-26 13:18:00 //////////////////////////////////////////////////////////////////*/ template< typename TData=ZNsMain::ZCEmpty /////// > class ZtCEventCond : public ZtCMutexCondData { public: typedef ZtCMutexCondData ZCMutexCondData; public: int WakeCond(){return this->WakeAllCond();} public: };/* template< typename TData=ZNsMain::ZCEmpty //////// > class ZtCEventCond : public ZtCMutexCondData*/ typedef ZtCEventCond<> CEventCond; #if defined(__USE_XOPEN2K) && !defined(__USE_MUTEX_COND_FOR_BARRIER__) template< typename TData=ZNsMain::ZCEmpty > class ZtCBarrier : public TData /////////// { protected: bool mb_IsValidID; ::pthread_barrier_t mh_BarrierID; // 0 À¸·Î ÃʱâÈ­ÇÒ ¼ö ¾ø´Ù. public : ZtCBarrier() { mb_IsValidID=false; }/* ZtCBarrier()*/ bool IsValid() const{return mb_IsValidID;} /*///////////////////////////////////////////////// ¡á Init() ¿Í Fini() ÀÇ ¸®ÅϰªÀ» ´Ù·ê ¶§´Â if(CBarrierObj.Init(3)==ZNsEnum::ZEBarrier_OK) ÀÌ·± ½ÄÀ¸·Î ÇÑ´Ù. /////////////////////////////////////////////////*/ int Init(unsigned AI_Count, const ::pthread_barrierattr_t* AP_Attr=0) { #if(_CODE_OLD_) if(mb_IsValidID==true) { ::pthread_barrier_destroy(&mh_BarrierID); mb_IsValidID=false; }/* if(mb_IsValidID==true)*/ #endif // _CODE_OLD_ int VI_Return = ::pthread_barrier_init(&mh_BarrierID, AP_Attr, AI_Count); if(VI_Return==ZNsEnum::ZEBarrier_OK) mb_IsValidID=true; return VI_Return; }/* int Init(unsigned AI_Count, const ::pthread_barrierattr_t* AP_Attr=0)*/ int Fini() { if(mb_IsValidID==false) return ZNsEnum::ZEBarrier_OK; mb_IsValidID=false; return ::pthread_barrier_destroy(&mh_BarrierID); }/* int Fini()*/ /*//////////////////////////////////////////////////////////////////////////// int pthread_barrier_wait(pthread_barrier_t *barrier); RETURN VALUE Upon successful completion, the pthread_barrier_wait() function shall return PTHREAD_BARRIER_SERIAL_THREAD for a single (arbitrary) thread synchronized at the barrier and zero for each of the other threads. Otherwise, an error number shall be returned to indicate the error. ERRORS The pthread_barrier_wait() function may fail if: EINVAL The value specified by barrier does not refer to an initialized barrier object. This function shall not return an error code of [EINTR]. The following sections are informative. ////////////////////////////////////////////////////////////////////////////*/ bool Wait() { return ::pthread_barrier_wait(&mh_BarrierID)!=ZNsEnum::ZEThread_Invalid; }/* bool Wait()*/ // ¾Æ·¡ 2 °³ÀÇ ¸â¹ö´Â À©µµ¿ì¿¡´Â ¾ø´Ù. bool GetShared(::pthread_barrierattr_t AH_BarrierAttr, int& ARRI_PShared) { return ::pthread_barrierattr_getpshared(&AH_BarrierAttr, &ARRI_PShared)==ZNsEnum::ZEThread_OK; }/* bool GetShared(::pthread_barrierattr_t AH_BarrierAttr, int& ARRI_PShared)*/ /* cf) PTHREAD_PROCESS_SHARED, PTHREAD_PROCESS_PRIVATE AI_PShared À» PTHREAD_PROCESS_SHARED ·Î ÁöÁ¤ÇÏ´Â °æ¿ì¿¡ mh_BarrierID Àº °øÀ¯ ¸Þ¸ð¸®¿¡ Á¸ÀçÇØ¾ß ÇÑ´Ù. */ bool SetShared(::pthread_barrierattr_t AH_BarrierAttr, int AI_PShared=PTHREAD_PROCESS_SHARED) { return ::pthread_barrierattr_setpshared(&AH_BarrierAttr, AI_PShared)==ZNsEnum::ZEThread_OK; }/* bool SetShared(::pthread_barrierattr_t AH_BarrierAttr, int AI_PShared=PTHREAD_PROCESS_SHARED)*/ public: };/* template< typename TData=ZNsMain::ZCEmpty > class ZtCBarrier : public TData /////////*/ #else // !defined(__USE_XOPEN2K) || defined(__USE_MUTEX_COND_FOR_BARRIER__) template< typename TData=ZNsMain::ZCEmpty > class ZtCBarrier : public TData /////////// { public : typedef ZtCMutexCondData<> ZCMutexCondData; protected: ZCMutexCondData mo_CCondData; bool mb_IsValidID; int mi_WaitCount; public : ZtCBarrier():mi_WaitCount(0){mb_IsValidID=false;} bool IsValid() const{return mb_IsValidID;} /*////////////////////////////////////////////////// ¡á Init() ¿Í Fini() ÀÇ ¸®ÅϰªÀ» ´Ù·ê ¶§´Â if(CBarrierObj.Init(3)==ZNsEnum::ZEBarrier_OK) ÀÇ ÇüÅ·ΠÇÑ´Ù. //////////////////////////////////////////////////*/ int Init(unsigned AI_Count) { if(mb_IsValidID==true) { mo_CCondData.FiniCond(); mb_IsValidID=false; }/* if(mb_IsValidID==true)*/ mi_WaitCount=AI_Count; int VI_Return = mo_CCondData.InitCond(); if(VI_Return==ZNsEnum::ZEThread_OK) { mb_IsValidID=true; return ZNsEnum::ZEThread_OK; }/* if(VI_Return==ZNsEnum::ZEThread_OK)*/ return ZNsEnum::ZEBarrier_NO; }/* int Init(unsigned AI_Count)*/ int Fini() { if(mb_IsValidID==false) return ZNsEnum::ZEThread_OK; mb_IsValidID=false; mi_WaitCount=0 ; return (mo_CCondData.FiniCond()==ZNsEnum::ZEThread_OK) ? ZNsEnum::ZEBarrier_OK : ZNsEnum::ZEBarrier_NO ; }/* int Fini()*/ bool Wait() { bool VB_IsOK=false; mo_CCondData.Lock(); { if(--mi_WaitCount<=0) VB_IsOK=(mo_CCondData.WakeAllCond()==ZNsEnum::ZEThread_OK); else VB_IsOK=(mo_CCondData.WaitCond ()==ZNsEnum::ZEThread_OK); //else } mo_CCondData.UnLock(); return VB_IsOK; }/* bool Wait()*/ public: };/* template< typename TData=ZNsMain::ZCEmpty > class ZtCBarrier : public TData /////////*/ #endif // !defined(__USE_XOPEN2K) || defined(__USE_MUTEX_COND_FOR_BARRIER__) typedef ZCSpinLockEasy ZCFastLockEasy; }/* namespace ZNsMain*/ #ifdef __INC_GLIB_ATOMIC_EXCHANGE__ #include namespace ZNsMain { /*/////////////////////////////////////////////////////// ¡á class ZtCAtomicIntSync<> Ä¿³ÎÀ̳ª ¶óÀ̺귯¸®ÀÇ µ¿±âÈ­ object ¸¦ »ç¿ëÇÏÁö ¾Ê°í µ¿±âÈ­¸¦ ±¸ÇöÇÏ°í ½ÍÀº °æ¿ì¿¡ »ç¿ëÇϴ Ŭ·¡½º ÅÛÇø´. volatile gint ¿¡ ´ëÇÑ ¿øÀÚÀû ¿¬»êÀ» ÀÌ¿ëÇϰí ÀÖ´Ù. ÀÏÁ¾ÀÇ lock-free ´Ù. ¡á int sched_yield(void) : IN A process can relinquish the processor voluntarily without blocking by calling sched_yield(). The process will then be moved to the end of the queue for its static priority and a new process gets to run. Note: If the current process is the only process in the highest priority list at that time, this process will continue to run after a call to sched_yield(). POSIX systems on which sched_yield() is available define _POSIX_PRIORITY_SCHEDULING in . RETURN VALUE On success, sched_yield() returns 0. On error, -1 is returned, and errno is set appropriately. ¡á ¸®´ª½º¿¡¼­ Á¤¼öÀÇ atomic ¿¬»ê ÇÔ¼ö´Â ¾Æ·¡ ¸í·ÉÀ¸·Î Á¶È¸ÇÒ ¼ö ÀÖ´Ù. find /usr/include/ | xargs grep 'atomic' | grep 'add' # or find /usr/include/ | xargs grep 'atomic' | grep 'increment' ¡á memory barrier °ü·Ã ÄÚµå´Â ¾Æ·¡¿Í °°´Ù. [root@localhost ~]# find /usr/include/ | xargs grep -n 'MEM_BARRIER' | more /usr/include/c++/4.1.1/tr1/boost_shared_ptr.h:155: _GLIBCXX_READ_MEM_BARRIER; /usr/include/c++/4.1.1/tr1/boost_shared_ptr.h:156: _GLIBCXX_WRITE_MEM_BARRIER; /usr/include/c++/4.1.1/tr1/boost_shared_ptr.h:175: _GLIBCXX_READ_MEM_BARRIER; /usr/include/c++/4.1.1/tr1/boost_shared_ptr.h:176: _GLIBCXX_WRITE_MEM_BARRIER; /usr/include/c++/4.1.1/x86_64-redhat-linux/bits/atomic_word.h:42:// #define _GLIBCXX_READ_MEM_BARRIER __asm __volatile ("":::"memory") /usr/include/c++/4.1.1/x86_64-redhat-linux/bits/atomic_word.h:46:// #define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("":::"memory") /usr/include/c++/4.1.1/bits/atomicity.h:53:#ifndef _GLIBCXX_READ_MEM_BARRIER /usr/include/c++/4.1.1/bits/atomicity.h:54:#define _GLIBCXX_READ_MEM_BARRIER __asm __volatile ("":::"memory") /usr/include/c++/4.1.1/bits/atomicity.h:56:#ifndef _GLIBCXX_WRITE_MEM_BARRIER /usr/include/c++/4.1.1/bits/atomicity.h:57:#define _GLIBCXX_WRITE_MEM_BARRIER __asm __volatile ("":::"memory") ¡á glib ¿¡ ÀÖ´Â ¾Æ·¡ ÇÔ¼ö¸¦ ÀÌ¿ëÇÑ´Ù. (glib ´Â gtk+ ¿ë ¶óÀ̺귯¸®ÀÌ´Ù.) gboolean g_atomic_int_compare_and_exchange ( volatile gint *atomic, gint oldval , gint newval ); //gboolean g_atomic_int_compare_and_exchange Compares oldval with the integer pointed to by atomic and if they are equal, atomically exchanges *atomic with newval. Also acts as a memory barrier. Returns : TRUE, if *atomic was equal oldval. FALSE otherwise ¡à ¾Æ·¡ ÇÔ¼öµµ Âü°íÇÑ´Ù. gboolean g_atomic_pointer_compare_and_exchange ( volatile gpointer *atomic, gpointer oldval, gpointer newval ); //gboolean g_atomic_pointer_compare_and_exchange ¡á -- 2010-04-03 18:05:00 ¡á ¸®´ª½º µî¿¡¼­ ZtCAtomicIntSync<> ÀÌ µ¿±âÈ­ object ¸¦ »ç¿ëÇØ¼­ (¹«°Ì°Ô) ±¸ÇöµÇ´Â °æ¿ì, ZtCAtomicIntSync<>::TypeSync ŸÀÔÀ» ÅëÇØ¼­ ¾î¶² µ¿±âÈ­ object ¸¦ »ç¿ëÇß´ÂÁö¸¦ ³ªÅ¸³¾ °ÍÀÌ´Ù. -- 2010-04-17 21:29:00 ¡á ¸®´ª½º¿¡¼­´Â alsa/iatomic.h ¿¡ atomic °ü·Ã ÇÔ¼ö°¡ ÀÖ±â´Â Çѵ¥, glib ÀÇ g_atomic_int_compare_and_exchange() ¿¡ ÇØ´çÇÏ´Â ÇÔ¼ö°¡ ¾ø´Ù. -- 2011-06-19 22:49:00 ¡á (¸®´ª½º centos)alsa/iatomic.h ¿¡¼­ atomic_add(), atomic_sub() µîÀÇ ÇÔ¼ö¸¦ º¼ ¼ö ÀÖ´Ù. static __inline__ void atomic_add(int i, atomic_t *v) { __asm__ __volatile__( ATOMIC_SMP_LOCK "addl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } static __inline__ void atomic_sub(int i, atomic_t *v) { __asm__ __volatile__( ATOMIC_SMP_LOCK "subl %1,%0" :"=m" (v->counter) :"ir" (i), "m" (v->counter)); } -- 2013-06-09 00:16:00 ///////////////////////////////////////////////////////*/ template< typename TTypeBase=ZNsMain::ZCEmpty > class ZtCAtomicIntSync : public TTypeBase { public : typedef ZtCAtomicIntSync TypeSync; public : enum{ZEUseAtomicInt=1}; public : enum ZESync { ZESync_Lock =0, ZESync_UnLock=1 };/* enum ZESync*/ private: volatile gint mi_SyncState; public : ZtCAtomicIntSync() { mi_SyncState=ZESync_UnLock; }/* ZtCAtomicIntSync()*/ ZtCAtomicIntSync(const TTypeBase& rhs) : TTypeBase(rhs) { mi_SyncState=ZESync_UnLock; }/* ZtCAtomicIntSync(const TTypeBase& rhs)*/ ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs) : TTypeBase(rhs) { mi_SyncState=ZESync_UnLock; }/* ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs)*/ ZtCAtomicIntSync& operator=(const TTypeBase& rhs) { this->TTypeBase::operator=(rhs); return *this; }/* ZtCAtomicIntSync& operator=(const TTypeBase& rhs)*/ ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs) { this->TTypeBase::operator=(rhs); return *this; }/* ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs)*/ void Lock() { #define __INTERLOCKED_COMP_EXCHANGE__ \ ::g_atomic_int_compare_and_exchange(&mi_SyncState, ZESync_UnLock, ZESync_Lock) while(__INTERLOCKED_COMP_EXCHANGE__==FALSE) { // ¾ÆÁ÷ Lock ÀÌ °É·Á ÀÖ´Â °æ¿ìÀÌ´Ù. ::sched_yield(); }/* while(__INTERLOCKED_COMP_EXCHANGE__==FALSE)*/ #undef __INTERLOCKED_COMP_EXCHANGE__ }/* void Lock()*/ void UnLock() { mi_SyncState=ZESync_UnLock; }/* void UnLock()*/ public: };/* template< typename TTypeBase=ZNsMain::ZCEmpty > class ZtCAtomicIntSync : public TTypeBase ///*/ }/* namespace ZNsMain */ #else // !__INC_GLIB_ATOMIC_EXCHANGE__ namespace ZNsMain { template< typename TTypeBase=ZNsMain::ZCEmpty > class ZtCAtomicIntSync : public TTypeBase { public : typedef ZCThreadMutexEasy TypeSync; public : enum{ZEUseAtomicInt=0}; private: TypeSync mo_CSyncEasy; public : ZtCAtomicIntSync() { }/* ZtCAtomicIntSync()*/ ZtCAtomicIntSync(const TTypeBase& rhs) : TTypeBase(rhs) { }/* ZtCAtomicIntSync(const TTypeBase& rhs)*/ ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs) : TTypeBase(rhs) { }/* ZtCAtomicIntSync(const ZtCAtomicIntSync& rhs)*/ ZtCAtomicIntSync& operator=(const TTypeBase& rhs) { }/* ZtCAtomicIntSync& operator=(const TTypeBase& rhs)*/ ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs) { this->TTypeBase::operator=(rhs); return *this; }/* ZtCAtomicIntSync& operator=(const ZtCAtomicIntSync& rhs)*/ void Lock() { mo_CSyncEasy.Lock(); }/* void Lock()*/ void UnLock() { mo_CSyncEasy.UnLock(); }/* void UnLock()*/ public: };/* template< typename TTypeBase=ZNsMain::ZCEmpty > class ZtCAtomicIntSync : public TTypeBase ///*/ }/* namespace ZNsMain */ #endif //!__INC_GLIB_ATOMIC_EXCHANGE__ #endif //__ZCPPMAIN__PROCESS_LINUX_H__