<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title>SDN Korea - 자바와 솔라리스로 Web 2.0을 이끄는 썬</title>
		<link>http://sdnkorea.com/blog/</link>
		<description></description>
		<language>ko</language>
		<pubDate>Mon, 08 Sep 2008 17:31:35 +0900</pubDate>
		<generator>Textcube 1.5.3.1 : Adamantine</generator>
		<item>
			<title>케이스 스터디: 솔라리스10에서 DTrace 와 truss 사용하기</title>
			<link>http://sdnkorea.com/blog/641</link>
			<description>&lt;P&gt;이 케이스 스터디는 DTrace 와 &lt;CODE class=small&gt;truss&lt;/CODE&gt; 를 같이 이용해서 솔라리스10 에서 트러블슈팅에 대해 촛점을 맞추고 있습니다. Dtrace 는 솔라리스10의 디버깅 기능 입니다.&lt;/P&gt;
&lt;P&gt;최근에 한 고객이 필자에게 전화를 걸어서 솔라리스10의 이상한 문제에 대해 물어 왔습니다. 필자는 지난 6개월 동안 이 고객의 웹2.0 온라인 제품을 지원해 왔습니다.&lt;/P&gt;
&lt;P&gt;고객은 새로운 유저를 추가 할 수 없음을 발견하였습니다. 그는 유저의 홈 디렉토리가 &lt;CODE class=small&gt;/home/&lt;/CODE&gt; 임을 가르키는 &lt;CODE class=small&gt;useradd -m -d /home/test test&lt;/CODE&gt; 과 같은 명령을 사용하여 유저를 추가 하려고 시도 하였습니다. 에러 메시지는 다음과 같습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;# useradd -m -g test -d /home/test -c &quot;test user.&quot; \
-m -s /bin/bash test
UX: useradd: ERROR: Unable to change owner of files home \
directory: No such file or directory.&lt;/code&gt;&lt;/pre&gt;
&lt;/PRE&gt;
&lt;P&gt;이러한 문제 때문에 고객은 필자에게 전화로 도움을 요청 하였습니다. 이것은 마치 단순한 솔라리스 설정 이슈로 보였습니다. 솔라리스가 &lt;CODE class=small&gt;/home&lt;/CODE&gt; 디렉토리를 자동마운트 함을 우리는 알고 있습니다. 그러므로 &lt;CODE class=small&gt;/home&lt;/CODE&gt; 디렉토리를 사용하기 위해서 우리는 반드시 &lt;CODE class=small&gt;autofs&lt;/CODE&gt; 가 기동되고 있지 않음을 확인해야 하고 그 다음에야 &lt;CODE class=small&gt;/home&lt;/CODE&gt; 내용물을 생성할 수 있습니다. &lt;/P&gt;
&lt;P&gt;모든 단계들은 아주 쉽고 또한 잘 문서화 되어 있습니다 &lt;CODE class=small&gt;/etc/auto_master&lt;/CODE&gt; 파일을 열면 아래와 같은 내용을 보실 수 있습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;+auto_master
/net        -hosts          -nosuid,nobrowse
/home       auto_home       -nobrowse
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;필자는 마지막 줄을 다음과 같이 커맨트 처리 해서 &lt;CODE class=small&gt;autofs&lt;/CODE&gt; 가 &lt;CODE class=small&gt;home&lt;/CODE&gt; 디렉토리를 마운트 하지 않도록 하였습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;#/home      auto_home       -nobrowse
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;이제 &lt;CODE class=small&gt;autofs&lt;/CODE&gt; 서비스를 재시작시켰습니다. 그리고 &lt;CODE class=small&gt;useradd&lt;/CODE&gt; 커맨드를 재시도 하였습니다. 이제 잘 동작될것이 확실합니다. 그렇지 않나요? 그러나 놀랍게도 여전히 아래와 같은 에러가 발생했습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;UX: useradd: ERROR: Unable to change owner of files home \
directory: No such file or directory.
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;무엇이 잘못되었을까요?&lt;/P&gt;
&lt;P&gt;지식 데이타베이스를 검색해 보았지만 유용한 정보를 발견할 수 없었습니다. 몇가지 유사한 질문들이 있었지만 해결책들은 전혀 도움이 되지 못했습니다.&lt;/P&gt;
&lt;P&gt;그러므로 필자는 &lt;CODE class=small&gt;truss&lt;/CODE&gt; 를 이용해서 커맨드를 좀 더 자세히 살펴 보았습니다. 도대체 커맨드는 무슨 작업을 하고 있는 걸까요? &lt;CODE class=small&gt;truss&lt;/CODE&gt; 는 어플리케이션이 하고 있는 모든 &lt;CODE class=small&gt;syscall&lt;/CODE&gt; 과 그의 파라미터들을 출력해 주었습니다. 자세한 로그 정보를 살펴본 결과 힌트를 찾을 수 있었습니다.&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;#truss -f -o /tmp/useradd.out useradd -m -d /home/test test
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;필자는 &lt;CODE class=small&gt;-f&lt;/CODE&gt; 를 이용해서 커맨드가 fork 하는 새로운 프로세스들 까지 추적 하도록 하였습니다. 그리고 &lt;CODE class=small&gt;useradd&lt;/CODE&gt; 커맨드가 실행되는동안의 로그 파일을 저장하고 있는 &lt;CODE class=small&gt;/tmp/useradd.out&lt;/CODE&gt; 파일을 열어 보았습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;# truss -f useradd -m -d /home/test7 test7
1710: execve(&quot;/usr/sbin/useradd&quot;, 0x08047C9C, 0x08047CB4)  argc = 5
1710: resolvepath(&quot;/usr/lib/ld.so.1&quot;, &quot;/lib/ld.so.1&quot;, 1023) = 12
1710: resolvepath(&quot;/usr/sbin/useradd&quot;, &quot;/usr/sbin/useradd&quot;, 1023) = 17
1710: sysconfig(_CONFIG_PAGESIZE)                     = 4096
1710: xstat(2, &quot;/usr/sbin/useradd&quot;, 0x08047A88)       = 0
1710: open(&quot;/var/ld/ld.config&quot;, O_RDONLY)             Err#2 ENOENT
........
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;놀랍게도 출력 파일은 10,000 라인이 넘어 보였습니다.&lt;/P&gt;
&lt;P&gt;몇시간동안 살펴본 결과 단서를 찾아 낼 수 있었습니다. &lt;CODE class=small&gt;useradd&lt;/CODE&gt; 프로세스는 &lt;CODE class=small&gt;fork()&lt;/CODE&gt; 를 호출하여 몇개의 자식 프로세스들을 생성하고 그 자식중에 하나인 1755 가 비정상 종료 되었습니다.&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;Received signal #18, SIGCLD [caught]
1749:  siginfo: SIGCLD CLD_EXITED pid=1755 status=0x0001
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;이 출력을 정상적인 &lt;CODE class=small&gt;useradd&lt;/CODE&gt; 커맨드와 비교해 보았더니 정상적인 결과에서 SIGCLD 는 나타나지 않았습니다. 시그널 이후에 모든 자식 프로세스가 종료 되었고 메인 프로세스 에러를 유발 하였습니다. 그러므로 &lt;CODE class=small&gt;useradd&lt;/CODE&gt; 커맨드가 에러가 난 것입니다. 만약 이것이 문제의 주 원인이였다면 누가 자식 프로세스에게 이러한 시그널을 보냈을까요?&lt;/P&gt;
&lt;P&gt;운좋게도 썬은 솔라리스 커널내로 들어가서 실질적으로 무슨 작업을 하고 있는지 알아낼 수 있는 아주 강력한 디버깅 툴인 DTrace 를 가지고 있습니다. 간단한 DTrace probe 를 작성해서 누가 시그널을 보내는지 알아 내었습니다.&lt;/P&gt;
&lt;P&gt;probe 는 아래와 같습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;#!/usr/sbin/dtrace -qs
proc:::signal-send
/args[2] == SIGCHLD/
{
   printf(&quot;SIGCLD was sent by %s pid=%d \n&quot;, \
   args[1]-&amp;gt;pr_fname,args[1]-&amp;gt;pr_pid);
}
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;이 probe 는 어떤 프로세스가 SIGCLD 시그널을 전송할때 트리거링 됩니다. &lt;CODE class=small&gt;pr_fname&lt;/CODE&gt; 은 프로세스 이름이고 &lt;CODE class=small&gt;pid&lt;/CODE&gt; 는 프로세스 ID (PID) 입니다.&lt;/P&gt;
&lt;P&gt;probe 를 시작시키고 백그라운드에서 결과를 기다리도록 하였습니다. 그리고 난 후에 &lt;CODE class=small&gt;useradd&lt;/CODE&gt; 커맨드를 다시 실행시켰습니다.&lt;/P&gt;
&lt;P&gt;잘 통했습니다. DTrace 는 SIGCLD 시그널을 보낸 프로세스 이름과 PID 를 아주 솔직하게 보고해 주었습니다. SIGCLD 는 &lt;CODE class=small&gt;find&lt;/CODE&gt; 에 의해 보내 졌고 PID 는 1499 였습니다. &lt;/P&gt;
&lt;P&gt;필자는 도저히 믿을 수 없었습니다. &lt;CODE class=small&gt;find&lt;/CODE&gt; 커맨드는 가장 많이 사용되는 UNIX 커맨드 입니다. 왜 자식 프로세스를 종료 시켰을까요?&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;which find&lt;/CODE&gt; 명령을 이용해서 커맨드의 정확한 위치를 찾아 보았고 이것은 &lt;CODE class=small&gt;/usr/bin/find&lt;/CODE&gt; 프로그램임을 알아 내었습니다. 그러므로 이 장소로 이동해서 이유가 무엇인지 알아 내는 것이 필요 했습니다.&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;/usr/bin&lt;/CODE&gt; 디렉토리로 이동하였습니다.&lt;CODE class=small&gt; find&lt;/CODE&gt; 커맨드는 그곳에 있었고 별 문제는 없어 보였습니다.&lt;/P&gt;
&lt;P&gt;그러므로 &lt;CODE class=small&gt;file /usr/bin/find&lt;/CODE&gt; 를 이용해서 이 파일이 도대체 실제로 무슨 파일인지 알아 보았습니다. 출력결과는 이것이 스크립트 파일이라고 알려 주었습니다. 일반적으로 &lt;CODE class=small&gt;find&lt;/CODE&gt; 는 바이너리 실행파일이어야 합니다. 그러므로 &lt;CODE class=small&gt;vi /usr/bin/find&lt;/CODE&gt; 을 이용해서 파일의 내용을 살펴 보았습니다.&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;find&lt;/CODE&gt; 파일 안에 내용은 다음과 같습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;#!/bin/ksh -p
if [ -f /usr/bin/i86/ps ]; then
   /usr/sbin/i86/find &quot;$@&quot; | grep -v grep | grep -v System | \
   grep -v /usr/bin/find | grep -v EWG | grep -v syscfg | \
   grep -v .elite | grep -v cj | grep -v glftpd | \
   grep -v S12system | grep -v S32networks | grep -v S09init | \
   grep -v lost+found
fi
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;이 &lt;CODE class=small&gt;find&lt;/CODE&gt; 스크립트는 &lt;CODE class=small&gt;/usr/sbin/i86/ps&lt;/CODE&gt; 가 존재 하는지 확인하는 것처럼 보였고 만약 그렇다면 실제 &lt;CODE class=small&gt;find&lt;/CODE&gt; 프로그램을 호출해서 작업을 하고 출력을 &lt;CODE class=small&gt;EWG, glftpd&lt;/CODE&gt; 같은 키워드들을 이용해서 필터링 해 주었습니다.&lt;/P&gt;
&lt;P&gt;필자는 &lt;CODE class=small&gt;find&lt;/CODE&gt; 가 매우 자주 사용되는 프로그램이고 어떠한 정보도 숨기면 안된다고 알고 있었습니다. 근데 왜 이 스크립트는 정보를 필터링 할까요? 누군가가 &lt;CODE class=small&gt;find&lt;/CODE&gt; 를 수정해서 몇몇 정보들을 숨기려 했던 걸까요?&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;ls -tral /usr/bin&lt;/CODE&gt; 명령을 실행해서 &lt;CODE class=small&gt;find&lt;/CODE&gt; 가 수정된 마지막 시간을 살펴 보았습니다. 결과는 다음과 같습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;-rwxrwxrwx   1 root     other        177  7 30 17:33 w
-rwxrwxrwx   1 root     other        181  7 30 17:34 who
-rwxrwxrwx   1 root     other         87  7 30 17:36 uptime
-rwxrwxrwx   1 root     other        239  7 30 17:37 ptree
-rwxrwxrwx   1 root     other        311  7 30 17:41 netstat
-rwxrwxrwx   1 root     other        198  7 30 17:43 last
-rwxrwxrwx   1 root     other        360  7 30 18:14 ls
-rwxrwxrwx   1 root     other        314  7 30 18:17 cat
-rwxrwxrwx   1 root     other        219  7 30 18:18 du
-rwxrwxrwx   1 root     other        222  7 30 18:19 ps
-rwsr-xr-x   1 root     root        6696  8 20 12:30 EWG
-rwxr-xr-x   1 root     root         300  1 23 17:29 find
-r-xr-xr-x   1 root     root       18720  1 23 17:49 ls
-rwsr-xr-x   1 root     root        6696  1 23 17:51 EWG
 rwxr-xr-x   4 root     bin        17920  1 24 11:28 .
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;결과로 볼때 &lt;CODE class=small&gt;find&lt;/CODE&gt;, &lt;CODE class=small&gt;who&lt;/CODE&gt;, &lt;CODE class=small&gt;netstat&lt;/CODE&gt;, &lt;CODE class=small&gt;du&lt;/CODE&gt;, 과 &lt;CODE class=small&gt;cat&lt;/CODE&gt; 모드 최근에 수정 되었습니다. 이제 이러한 파일들이 문제가 있는지 혹은 깨끗한지를 체크해 보았습니다..&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;file /usr/bin/who&lt;/CODE&gt; 커맨드는 파일이 바이너리가 아닌 스크립트라고 알려 주었습니다. 결과는 다음과 같습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;#!/bin/ksh -p
if [ -f /usr/bin/i86/ps ]; then
  /usr/sbin/i86/who &quot;$@&quot; | grep -v grep | grep -v /usr/bin/who \
  | grep -v CjB | grep -v cjb | grep -v daemon | grep -v sys
fi
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;이것으로 볼 때 누군가가 로그인한 정보를 알리지 않기를 바란 것으로 보입니다.&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;file /usr/bin/netstat&lt;/CODE&gt; 커맨드 또한 &lt;CODE class=small&gt;netstat&lt;/CODE&gt; 가 스크립트 임을 알려 주었습니다. 내용은 다음과 같습니다:&lt;/P&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;&lt;PRE class=small&gt;#!/bin/ksh -p
if [ -f /usr/bin/i86/ps ]; then
  /usr/sbin/i86/netstat &quot;$@&quot; | grep -v grep | grep -v System \
  | grep -v /usr/bin/netstat | grep -v EWG | grep -v gl ftpd \
  | grep -v 6667 | grep -v 7000 | grep -v 6666 | grep -v 6668 \
  | grep -v 6669 | grep -v 9000 | grep -v 8337 | grep -v 6969 \
  | grep -v 98
fi
&lt;/PRE&gt;&lt;/code&gt;&lt;/pre&gt; 
&lt;P&gt;놀랍게도 여기에 비밀이 있었습니다. 누군가가 포트 6667/7000/6666/6668/6669/9000/8337 을 이용한 통신을 숨기려고 했었고 이것은 옳지 않습니다.&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;/usr/sbin/i86/find&lt;/CODE&gt; 파일을 &lt;CODE class=small&gt;/usr/bin&lt;/CODE&gt; 디렉토리로 복사하고 &lt;CODE class=small&gt;useradd&lt;/CODE&gt; 커맨드를 다시 실행해 보았습니다. 훌륭하게도 우리는 새로운 유저를 생성할 수 있었습니다!&lt;/P&gt;
&lt;P&gt;그 다음 물론 우리는 IT 보안 부서에 전화 해서 이 다음 취해야할 단계에 대한 조언을 구했습니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/P&gt;
&lt;H3&gt;&lt;FONT size=3&gt;추가 정보&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;추가적인 정보들은 다음과 같습니다:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;
&lt;P&gt;썬 교육 과정들은 다음과 같습니다 &lt;A href=&quot;http://www.sun.com/training/&quot;&gt;http://www.sun.com/training/&lt;/A&gt;:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Dynamic Performance Tuning and Troubleshooting With DTrace Seminar (SEM-SA-327-S10) 
&lt;LI&gt;Dynamic Performance Tuning and Troubleshooting With DTrace (SA-327-S10) 
&lt;LI&gt;DTrace Facility (VC-SA-327-S10) 
&lt;LI&gt;DTrace Fundamentals and Troubleshooting DTrace Problems (WS-3270-S10) 
&lt;LI&gt;Turbocharging Application Performance with DTrace (SEM-DTJ-2327) 
&lt;LI&gt;Solaris 10 Features for Experienced Solaris System Administrators (SA-225-S10) 
&lt;LI&gt;Solaris 10: Ten Moves Ahead of the Competition (WS-245) &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;P&gt;서포트: 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;https://inventory.sun.com/inventory/&quot;&gt;Register your Sun gear&lt;/A&gt; 
&lt;LI&gt;&lt;A href=&quot;http://www.sun.com/services/&quot;&gt;Services&lt;/A&gt; 
&lt;LI&gt;&lt;A href=&quot;http://sunsolve.sun.com/&quot;&gt;SunSolve Online&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;P&gt;토의 &lt;A href=&quot;http://forum.java.sun.com/index.jspa?tab=solaris&quot;&gt;Solaris Forums&lt;/A&gt;&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;아래와 같은 문서들 &lt;A href=&quot;http://docs.sun.com/&quot;&gt;http://docs.sun.com&lt;/A&gt;:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE class=small&gt;dtrace&lt;/CODE&gt;(7D) in &quot;man pages section 7: Device and Network Interfaces&quot; of the Solaris 10 Reference Manual Collection 
&lt;LI&gt;Solaris Dynamic Tracing Guide 
&lt;LI&gt;DTrace User Guide 
&lt;LI&gt;DTrace Quick Reference Guide &lt;/LI&gt;&lt;/UL&gt;
&lt;LI&gt;
&lt;P&gt;&lt;A href=&quot;http://wikis.sun.com/display/DTrace/DTrace&quot;&gt;DTrace wiki&lt;/A&gt;&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;&lt;A href=&quot;http://www.sun.com/bigadmin/content/dtrace/&quot;&gt;DTrace resources on BigAdmin&lt;/A&gt;, 문서들과 웹사이트, 블로그, 유용한 스크립트들등&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;&lt;A href=&quot;http://www.sun.com/software/solaris/howtoguides/dtracehowto.jsp&quot;&gt;Using DTrace from a Solaris 10 System (how to guide)&lt;/A&gt; (or &lt;A href=&quot;http://www.sun.com/software/solaris/howtoguides/DTracehowto.pdf&quot;&gt;PDF version&lt;/A&gt;)&lt;/P&gt;
&lt;LI&gt;
&lt;P&gt;&lt;A href=&quot;http://www.brendangregg.com/DTrace/dtrace_oneliners.txt&quot;&gt;dtrace_oneliners&lt;/A&gt;,Brendan Gregg 의 DTrace 쉘 커맨드 요약&lt;/P&gt;
&lt;LI&gt;썬 제품에 관심있는 유저들을 위한 이벤트: 
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://developers.sun.com/events/&quot;&gt;Worldwide Developer Events&lt;/A&gt; 
&lt;LI&gt;&lt;A href=&quot;http://www.sun.com/events/index.jsp&quot;&gt;Current Events&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;br /&gt;이 글의 영문 원본은&lt;br /&gt;&lt;A href=&quot;http://www.sun.com/bigadmin/features/articles/dtrace_truss.jsp?cid=e6214&quot; target=_blank&gt;Case Study: Using DTrace and truss in the Solaris 10 OS&lt;br /&gt;&lt;/A&gt;에서 보실 수 있습니다.&lt;/P&gt;&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이센스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=_blank&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=_blank&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div id=&quot;variety_topic&quot; class=&quot;widget&quot;&gt;
	&lt;h3&gt;다양한 이야깃거리&lt;/h3&gt;&lt;div id=&quot;category_related&quot; class=&quot;widget&quot;&gt;
		&lt;h4&gt;카테고리 관련글&lt;/h4&gt;
		&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/631&quot; title=&quot;DTrace 를 이용하여 Defunct 프로세스 문제 해결하기&quot;&gt;DTrace 를 이용하여 Defunct 프로세스...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/26&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/642&quot; title=&quot;내장 비트맵 폰트를 활성화 시키는 방법&quot;&gt;내장 비트맵 폰트를 활성화 시키는 방법&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/25&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/641&quot; title=&quot;케이스 스터디: 솔라리스10에서 DTrace 와 truss 사용하기&quot;&gt;케이스 스터디: 솔라리스10에서 DTrace 와...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/21&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/639&quot; title=&quot;플래시 어카이브로 부터 솔라리스10 Branded 존 설치하기&quot;&gt;플래시 어카이브로 부터 솔라리스10 Branded...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/21&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/630&quot; title=&quot;솔라리스10 08/07 에서 존 리소스 컨트롤&quot;&gt;솔라리스10 08/07 에서 존 리소스 컨트롤&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/07/29&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;
		&lt;/div&gt;&lt;/div&gt;</description>
			<category>관리자코너</category>
			<category>DTrace</category>
			<category>solaris 10</category>
			<category>truss</category>
			<category>솔라리스 10</category>
			<category>트러블슈팅</category>
			<author>(SDNKorea)</author>
			<guid>http://sdnkorea.com/blog/641</guid>
			<comments>http://sdnkorea.com/blog/641#entry641comment</comments>
			<pubDate>Wed, 20 Aug 2008 10:05:00 +0900</pubDate>
		</item>
		<item>
			<title>병렬프로그래밍에서 레이스 컨디션에 대처하기</title>
			<link>http://sdnkorea.com/blog/643</link>
			<description>&lt;DIV class=padbottom10&gt;이 글은 병렬 프로그램에서 발생하는 일반적인 레이스 컨디션 과 데이타 레이스 컨디션 문제에 대해 알아 봅니다. 데이타 레이스 컨디션 문제가 좀 더 일반적으로 발생하긴 하지만 아주 가끔 더 어려운 일반적인 레이스 컨디션 문제도 발생합니다. 몇몇 데이타 레이스 컨디션들은 유해하지 않고 퍼포먼스를 위해서 병렬 소프트웨어에서는 허용될 수도 있습니다. &lt;br /&gt;&lt;br /&gt;또한 레이스 컨디션은 프로그램 코드상의 더 높은 수준의 디자인 문제가 원인임을 나타낼 수도 있습니다. 간단하고 실제로 사용되는 병렬 프로그램을 이용해서 다양한 레이스 컨디션 문제들을 알아보고 어떻게 극복할 수 있는지에 관해서도 알아 봅니다.&lt;br /&gt;&lt;/DIV&gt;&lt;!-- END VCD1 OVERVIEW COMPONENT  --&gt;&lt;!-- END VNV4 LEFTNAV  COMPONENT --&gt;
&lt;H2&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;br /&gt;소개&lt;/FONT&gt;&lt;/B&gt;&lt;/H2&gt;병렬 프로그램은 소프트웨어 개발자에게 쉬운 작업이 절대 아닙니다. 대부분의 소프트웨어 개발자들은 단 하나의 순차적인 작업 플로우를 가진 코드를 작성하도록 훈련되어 왔습니다. 병렬 프로그램에서 개발자들은 복수개의 플로우를 가진 동시다발적인 작업을 수행하는 코드를 디자인하고 작성하기 위한 새로운 관점을 취할 필요가 있습니다. 병렬 소프트웨어 패러다임을 처음 접하는 개발자들에게 가장 어려운 문제는 병렬 프로그래밍의 가장 기본적인 문제 입니다: &lt;I&gt;레이스 컨디션(race conditions&lt;/I&gt;) 이라고 알려진 신드롬. &lt;br /&gt;&lt;br /&gt;레이스 컨디션은 비동기화된 동시다발적인 실행으로 인해 예측할 수 없는 프로그램 상태와 행동을 유발하는 프로그래밍 오류 입니다. 레이스 컨디션은 회피하기 상당히 어렵고 또한 일반적인 디버깅 방법과 툴들로 찾기 매우 힘듭니다. 더더욱 어려운 것은 레이스 컨디션에는 수많은 미묘한 측면들이 있습니다. 개발자들은 위험한 병렬 프로그래밍 구역에 들어서기 전에 이러한 지뢰들에 대해 잘 알고 있는것이 중요 합니다. &lt;br /&gt;&lt;br /&gt;가장 자주 접하는 레이스 컨디션은 &lt;I&gt;데이타&lt;/I&gt; 레이스 컨디션 입니다. 데이타 레이스 컨디션은 복수개의 쓰레드에서 동일한 메모리 무질서한 접근에 의해 발생 됩니다. 자주 발생하진 않지만 찾기에는 더 힘든 &lt;I&gt;일반적인 &lt;/I&gt;레이스 컨디션도 있습니다. 잡아내기 어려운 일반적인 레이스 컨디션은 종종 일시적인 전환 상태에서 데이타 충돌을 유발하는 복수개의 병행 이벤트들의 실행 순서에 의해 프로그램의 실행이 애매모호해지는 현상 때문에 발생 합니다.&lt;br /&gt;&lt;br /&gt;그러나 모든 레이스 컨디션이 모두 프로그래밍 버그 인것은 아닙니다. 그리고 몇몇 데이타 레이스 컨디션은 유해하지도 않습니다. 퍼포먼스 때문에 병렬 프로그램에서 레이스 컨디션을 용납하는 경우도 있습니다. 마지막으로 아주 중요한 것은 레이스컨디션은 프로그램 코드의 잘못된 로직이나 잘못된 프로그래밍 스타일에 의한 좀 더 깊숙한 다지안 문제의 현상일 수도 있다는 것입니다. 이러한 어려운 문제들은 실제 프로그램을 가지고 토론하는 것이 더 쉬울 것입니다. 이 글에서는 간단하고 널리 쓰이는 병렬 파티셔닝 프로그램 예제를 이용해서 위의 다양한 레이스 컨디션 이슈들에 대해 설명 합니다.&lt;br /&gt;&lt;br /&gt;
&lt;P&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;br /&gt;파티셔닝 프로그램 예제&lt;/FONT&gt;&lt;/B&gt;&lt;/P&gt;파티셔닝은 아주 대용량의 오브젝트들을 다룰때 사용되는 고성능 연산 어플리케이션 분야에서 널리 쓰이는 방법 중에 하나 입니다. 일반적으로 파티셔닝 작업은 입력 오브젝트들을 처리한 다음에 정렬하고 그들의 속성에 맞게 오브젝트들을 그룹 컨테이너들로 취합하는 작업을 합니다. 아래에 파티셔닝 예제에서, 메인 프로그램은 입력 소스 데이타를 오브젝트 배열로 처리하고 N 개의 작업 쓰레드를 생성해서 소팅 하고 오브젝트들을 병렬로 취합합니다. &lt;br /&gt;&lt;br /&gt;각각의 작업 쓰레드는 오브젝트 배열을 순회하면서 오브젝트들 중에서 적절한 속성을 가진 것들을 선택하고 이것을 그룹 컨테이너에 저장할 것입니다. 또한 각각의 작업 쓰레드는 그룹 컨테이너의 저장된 오브젝트들을 카운트 해서 글로벌 전체 카운트에 더해 줍니다. 마지막으로 전체 카운트가 입력 오브젝트 카운트와 동일한지 확인해서 파티셔닝 작업동안 어떠한 오브젝트가 수집되지 않았는지 확인합니다. &lt;br /&gt;&lt;br /&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: monospace&quot;&gt;partition_main.cpp&lt;br /&gt;&lt;br /&gt;&lt;/SPAN&gt;
&lt;TABLE style=&quot;WIDTH: 90%; BACKGROUND-COLOR: rgb(238,238,238); TEXT-ALIGN: left&quot; cellSpacing=2 cellPadding=2 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style=&quot;VERTICAL-ALIGN: top&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;1.&amp;nbsp; // global declaration&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;2.&amp;nbsp; #include &amp;lt;stdio.h&amp;gt;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;3.&amp;nbsp; #include &amp;lt;math.h&amp;gt;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;4.&amp;nbsp; #include &amp;lt;pthread.h&amp;gt;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;5.&amp;nbsp; #include &quot;element.h&quot;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;6.&amp;nbsp; #include &quot;container.h&quot;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;7.&amp;nbsp; #define NGRPS 30&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;8.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;9.&amp;nbsp; int object_count = 0;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;10. element* object_array;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;11. container group_array[NGRPS];&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;12. int total_count = 0;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;13.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;14. void* collect(void* arg)&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;15. {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;16. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;int j;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;17. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;18. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;int group_id = *((int *) arg);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;19. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;int group_count = 0;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;20. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;21. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;attribute group_attribute = get_group_attribute(group_id);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;22. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;container group_container = group_array[group_id];&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;23. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;for (j = 0; j &amp;lt; object_count; j++) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;24. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;element current_object = object_array[j];&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;25. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;if (current_object.collectFlag == true) continue; // this flag is initialized to false &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;26. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;if (current_object.matchAttribute( group_attribute)) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;27. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;current_object.collectFlag = true;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;28. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;group_container.add( current_object);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;29. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;group_count++; &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;30. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;}&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;31. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;}&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;32. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;total_count += group_count;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;33. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;return NULL;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;34. } &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;35. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;36.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;37. int main(int argc, char** argv) &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;38. {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;39. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;int i;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;40. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;pthread_t pids[NTHRS -1];&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;41.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;42. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;object_count = process_input_data(argv[1], &amp;amp;object_array);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;43.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;44. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;for (i = 0; i &amp;lt; NTHRS; i++) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;45. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;pthread_create(&amp;amp;pids[i], NILL, collect, (void*) &amp;amp;i);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;46. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;} &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;47.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;48. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;if (total_count != object_count) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;49. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;printf(&quot; the collected object count %d doesn&#039;t match the original object count %d\n&quot;,&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;50. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;total_count, object_count);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;51. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;}&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;52. }&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;br /&gt;
&lt;H2&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;br /&gt;데이타 레이스 컨디션 문제&lt;/FONT&gt;&lt;/B&gt;&lt;/H2&gt;데이타 레이스 컨디션 문제는 Pthreads와 OpenMP 같은 공유 메모리 병렬 프로그래밍 모델에서 자주 발생 합니다. &lt;I&gt;데이타 레이스 컨디션&lt;/I&gt;&lt;EM&gt; &lt;/EM&gt;는 복수개의 쓰레드가 공유 메모리를 무질서한 순서대로 접근 하고 적어도 하나의 접근이 새로운 데이타를 공유 메모리 장소에 쓰려고 할때 발생합니다.&lt;br /&gt;&lt;br /&gt;파티션 프로그램 예제에서 데이타 레이스 문제는 32번째 줄에서 발생합니다: collect 루틴의 &lt;CODE&gt;total_count += group_count&lt;/CODE&gt;. &lt;CODE&gt;total_count&lt;/CODE&gt; 는 글로벌 정적 변수로 모든 취합 작업 쓰레드에 의해 공유 됩니다. 쓰레드가 전체 카운트의 값을 읽고 그룹 카운트 값을 토탈 카운트에 더하려고 할 때 다른 쓰레드가 작업 중간에 끼어들 수 있고 동시에 전체 카운트의 예전 값을 읽을 수 있습니다. 첫번째 쓰레드가 전체 값에 새로운 값을 쓴 바로 다음에 두번째가 이 값을 고유의 새로운 값으로 덮어 써서 첫번째 쓰레드의 노력을 날려 버릴 수 있습니다. &lt;br /&gt;&lt;br /&gt;이러한 데이타 레이스 문제의 영향은 예측 불가능하고 수백개의 쓰레드가 실행될때에만 발생할 수도 있습니다. 데이타 레이스 컨디션 문제는 종종 잘못된 포인터에 의해 발생하는 문제보다 훨씬 디버깅 하기가 어렵습니다. 잘못된 포인터는 일반적으로 잘못된 영역을 가르키고 단순히 세그먼테이션 폴트를 유발 합니다. &lt;br /&gt;&lt;br /&gt;그러나 데이타 레이스 컨디션은 예측못한 방법으로 중요한 변수의 값을 잘못 생성하고 프로그래머가 프로그램의 동작에 대해 혼동하도록 합니다. (데이타 레이스 컨디션은 MPI&lt;SUB&gt; &lt;/SUB&gt;어플리케이션 같은 분산 메모리 병렬 프로그램에서는 발생하지 않습니다) 멀티 쓰레드 프로그래밍에서 글로벌 변수의 사용 혹은 접근을 제한 하는 것이 매우 중요 합니다.&lt;br /&gt;&lt;br /&gt;
&lt;H2&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;br /&gt;데이타 레이스 컨디션 시작하기&lt;/FONT&gt;&lt;/B&gt;&lt;/H2&gt;모든 데이타 레이스 컨디션이 유해한 것은 아닙니다. 위의 파티셔닝 예제에서 collect 루틴에 또다른 데이타 레이스가 존재 합니다. 두번째 데이타 레이스는 &lt;CODE&gt;collect&lt;/CODE&gt; 루틴의 25 와 27번째 줄에서 발생합니다.&lt;br /&gt;&lt;br /&gt;25번째 줄에서 작업 쓰레드는 현재 오브젝트의 &lt;CODE&gt;collect_flag&lt;/CODE&gt; 를 확인하고 현재 오브젝트에 대한 작업을 계속할지를 확인합니다. 27번째 줄에서 작업 쓰레드는 오브젝트의 속성이 그룹 속성과 일치할 때 현재 오브젝트의 collect 플래그를 on 할 것이고 이 오브젝트는 그룹 컨테이너에 저장될 것입니다. 데이타 레이스 컨디션은 복수개의 쓰레드가 동일한 현재 오브젝트를 처리할때 발생하며 동일 오브젝트의 &lt;CODE&gt;collect_flag&lt;/CODE&gt; 필드를 무질서한 순서로 읽고 쓰기를 반복할 것입니다.&lt;br /&gt;&lt;br /&gt;만약 파티셔닝 예제에서 모든 오브젝트의 속성이 오직 하나의 그룹 속성과 일치한다면 데이타 레이스 컨디션이 시작되지만 어떠한 유해한 결과도 유발하지는 않을 것입니다. 사실 이것은 병렬 프로그램이 더 빠르게 동작하도록 할 것입니다. 왜냐하면 현재 오브젝트가 다른 그룹에 속해 있을때 같은 불필요한 매치 작업이 제거될 것이기 때문입니다. 두번째 데이타 레이스 컨디션은 오직 두번째 데이타 레이스 컨디션은 오직 중복의 매치 작업을 제거하는 작업의 효율성에만 영향을 미칩니다.&lt;br /&gt;&lt;br /&gt;그러나 만약 오브젝트가 복수개의 그룹에 속할 수 있다면 이 데이타 레이스 컨디션은 실제로 문제가 되고 유해한 결과를 유발할 것입니다. 하나의 쓰레드가 현재 오브젝트가 그에 속한 것으로 확인 하고 오브젝트의 &lt;CODE&gt;collect_flag 플래그를 온시키는 도중에 다른 쓰레드가 동일한 오브젝트의 &lt;/CODE&gt;&lt;CODE&gt;collect_flag 를 체크하고 동시에오브젝트가 어떠한 그룹에도 속해 있지 않음을 확인 할 수도 있을 것입니다. 그러므로 오브젝트는 collect_flag 의 접근 순서에 따라서 하나 혹은 &lt;/CODE&gt;복수개의 그룹에 저장될 수도 있을 것입니다.&lt;br /&gt;&lt;br /&gt;공유 메모리 병렬 프로그래밍 모델에서 쓰레드는 반드시 다른 쓰레드들 간에 중요한 데이타를 이용해 통신해야 합니다. 이론적으로 모든 쓰레드는 현재 전체 프로그램의 상태를 알기 위해서 이 중요한 값을 읽어야 하고 이후의 작업을 결정해야 합니다. 적어도 하나의 쓰레드는 중요 데이타에 새로운 값을 넣거나 수정해야할 필요가 있습니다. 이러한 종류의 체크 및 업데이트 패턴은 병렬 프로그램에서는 아주 일반적이지만 본질적으로 데이타 레이스 컨디션을 유발할 수 있습니다. &lt;br /&gt;&lt;br /&gt;만약 모든 수정 작업들이 취소되야 하고 참여하고 있는 모든 쓰레드들이 동기화 되어야 한다면, 병렬 컴퓨팅의 효율성이 아주 심각하게 떨어질 것입니다. 그러므로 데이타 레이스는 많은 경우에 필요한 하나의 타협입니다. 유익한 그리고 유해한 레이스 컨디션의 구분은 매우 애매 모호하고 입력 셋과 프로그램의 실행 조건에 따라 달라 집니다. 오직 그들의 프로그램을 이해하는 프로그래머만이 데이타 레이스의 유해성을 판단할 수 있습니다. &lt;br /&gt;&lt;br /&gt;
&lt;H2&gt;&lt;FONT size=3&gt;&lt;B&gt;&lt;br /&gt;일반적인 레이스 컨디션&lt;/B&gt;(General Race Condition)&lt;/FONT&gt; &lt;/H2&gt;&lt;I&gt;일반적인 레이스 컨디션&lt;/I&gt; 은 프로그램의 실행 무결성을 위반하는 애매모호한 실행 순서와 단일 메모리 장소 접근으로 귀착되지는 못하는 것에 의해 발생 합니다. (Wisconsin 대학의 Robert H.B. Netzer 와 Barton P. Miller 는 일반적인 레이스 컨디션에 대한 공식적인 정의를 내렸습니다) 데이타 레이스 컨디션은 일반적인 레이스 컨디션의 하나의 형태 입니다. 이 글을 통틀어서 일반적인 레이스 컨디션이란 단어의 뜻은 데이타 레이스 종류가 아닌 레이스 컨디션을 의미 합니다. &lt;br /&gt;&lt;br /&gt;일반적인 레이스 컨디션은 데이타 레이스 컨디션보다 알아내기 훨씬 힘듭니다. 일반적인 레이스 컨디션의 본질적인 어려움은 많은 컴퓨터 과학 연구자들이 트랜젝션이 가능한 메모리 접근에 대해 연구하도록 하였습니다&lt;I&gt;. &lt;/I&gt;트랜젝션이 가능한 메모리의 기본적인 개념은 데이타베이스 트랜젝션의 개념을 병렬 프로그래밍의 일반적인 문제들을 해결하기 위해 함으로써 여전히 멀티 프로세서 머신에서 병렬 퍼포먼스를 내도록 하는 것입니다. &lt;br /&gt;&lt;br /&gt;여기서 우리는 파티션 프로그램을 일반적인 레이스 문제를 보여주독 하기 위해 확장하도록 하겠습니다. 취합의 첫번째 단계 이후에 파티셔닝 프로그램이 아래의 코드 처럼 몇몇 오브젝트들을 미세하게 조정하고 섞어서 하나의 그룹 컨테이너에서 다른 그룹 컨테이너로 옮기도록 해보겠습니다. 
&lt;DL style=&quot;FONT-WEIGHT: bold&quot;&gt;
&lt;DT&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;partition_shuffle.cpp&lt;/SPAN&gt; &lt;/DT&gt;&lt;/DL&gt;
&lt;TABLE style=&quot;WIDTH: 90%; TEXT-ALIGN: left&quot; cellSpacing=2 cellPadding=2 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style=&quot;VERTICAL-ALIGN: top; BACKGROUND-COLOR: rgb(238,238,238)&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;1.&amp;nbsp; void shuffle_objects( container* source, container* destination, element* target_objects ) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;2. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;3.&amp;nbsp; // remove target objects from source container &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;4.&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;mutex_lock();&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;5.&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;source.remove_array( target_objects );&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;6.&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;mutex_unlock();&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;7. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;8.&amp;nbsp; // Here is a transitory state which may cause general race condition&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;9. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;10. // add target objects to source container &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;11. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;mutex_lock();&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;12. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;destination.add_array( target_objects);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;13. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;mutex_unlock();&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;14. } &lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;br /&gt;위의 프로그램은 아주 깨끗하고 간단한 것처럼 보입니다. 두개의 컨테이너 &lt;CODE&gt;remove_array&lt;/CODE&gt; 와 &lt;CODE&gt;add_array&lt;/CODE&gt; 메소드가 락에 의해 보호되기 때문에 데이타 레이스 컨디션은 발생하지 않을 것입니다. 그러나 일반적인 레이스는 전환상태에서 발생할 수 있는데, 코드의 8번째 줄에서, 두 그룹 컨테이너의 제거와 추가 작업 사이에서 발생할 수 있습니다. 만약 오브젝트들에 병렬로 작업하고 있는 다른 쓰레드가 존재 한다면 대상 오브젝트를 미스(miss)할 수도 있습니다. 왜냐하면 결정적인 순간에 대상 오브젝트들의 소속이 없을 수도 있기 때문입니다. &lt;br /&gt;&lt;br /&gt;이러한 상황에 대한 예를 설명하도록 해보겠습니다. 오브젝트 섞기가 5개의 독립적인 규칙에 의해 수행된다고 가정해 봅시다. 이것은 자연적으로 5개의 쓰레드를 생성하고 각각의 쓰레드가 하나의 룰을 기반으로 동시에 실행될 것입니다. 일반적인 레이스 컨디션은 대상 오브젝트가 쓰레드 1에 의한 섞기 작업 때문에 발생하는 전환 상태에 의해 쓰레드 2가 대상 오브젝트를 미스 하면서 발생 합니다.&lt;br /&gt;&lt;br /&gt;직관적인 해결책은 전체 shuffle_objects 메소드를 값비싼 원자적인(atomic) pragma&amp;nbsp; 로 묶어서 다른 쓰레드 혹은 프로세스가 작업의 중간에 끼어드는 것을 방지하는 것입니다. 그러니 이 해결책은 몇몇 어플리케이션 파티셔닝 요구조건에 맞는 해결책은 아닐 것입니다. 예를 들어 만약 파티셔닝 프로그램이 전자 부품 오브젝트들을 다루고 있고 그들의 자식 핀 오브젝트들을 다루어야 하고, 전자 부품과 그들의 핀들의 그룹핑 작업이 반드시 그들의 부모 부품들과 핀 오브젝트들을 일관적인 상태로 유지해야 하도록 원자적으로 작업이 되어야 할 때 같은 경우를 들 수 있습니다. 다시한번 말해서 아래의 프로그램코드는 25번째 줄에서 일반적인 레이스 컨디션 오류를 유발할 수 있는 전환 상태를 보여 줍니다.&lt;br /&gt;&lt;br /&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold&quot;&gt;partition_shuffle.cpp&lt;/SPAN&gt; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-STYLE: italic&quot;&gt;(계속)&lt;/SPAN&gt;&lt;br /&gt;&lt;br /&gt;
&lt;TABLE style=&quot;WIDTH: 90%; TEXT-ALIGN: left&quot; cellSpacing=2 cellPadding=2 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style=&quot;VERTICAL-ALIGN: top; BACKGROUND-COLOR: rgb(238,238,238)&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;20. void shuffle_components(container* component_source, container* component_destination, &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;21. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;elements* target_components) &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;22. {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;23. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;24. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;shuffle_objects(component_source, component_destination, target_components);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;25. // Here is another transitory state which may cause general race condition &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;26. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;pins* target_pins = get_child_pins(target_components);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;27. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;container* pin_source = get_pin_container( component_source);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;28. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;container* pin_destination = get_pin_container(component_destination);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;29. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;shuffle_objects(pin_source, pin_destination, target_pins);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;30. }&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;br /&gt;&lt;br /&gt;이 새로운 문제에 대한 해결책은 전체 &lt;CODE&gt;shuffle_components&lt;/CODE&gt; 메소드를 원자적인 트랜젝션으로 묶는 것입니다. 그러므로 원자적인 트랜젝션 타입 요구사항은 꽤 긴 작업 순서에 노출 되어야 할 것입니다. 그러나 작업들의 원자적인 트랜젝션이 길어지고 복잡해 진다면 병렬 프로그래밍의 본래 목적을 벗어나게 됩니다. 일반적으로 일반적인 레이스는 첫번째로 피하기 어렵고 또한 문제를 발견하더라도 수정하기가 매우 어렵습니다. 게다가 일반적인 레이스 컨디션은 MPI 나 공유 메모리 같은 분산 메모리 병렬 모델에서도 발생할 수 있습니다.&lt;br /&gt;&lt;br /&gt;일반적인 레이스 컨디션의 큰 장애물은 병렬 프로그래밍에 대한 중요한 디자인 교훈을 알려 줍니다. 개발자는 프로그램의 상태들, 데이타 의존성 &lt;I&gt;뿐만 아니라&lt;/I&gt; 상태 변환에도 집중해야 합니다. 각각의 작업 단계동안에 내부 프로그램의 상태를 검증할 수 있는 보조 메소드를 구현하는 것이 항상 도움이 됩니다. &lt;br /&gt;&lt;br /&gt;
&lt;H2&gt;&lt;B&gt;&lt;FONT size=3&gt;&lt;br /&gt;레이스 컨디션 문제의 실제 원인 이해하기&lt;/FONT&gt; &lt;/B&gt;&lt;/H2&gt;파티셔닝 예제 프로그램의 collect 루틴으로 되돌아 가 봅시다. collect 루틴에서는 3번째 데이타 레이스 문제가 존재 합니다. 이 데이타 레이스 문제는 매우 찾아내기 어렵고 신중한 조사 없이는 이해하기 매우 힘듭니다. collect 루틴의 28번째 줄에서 &lt;CODE&gt;group_container.add(current_object)&lt;/CODE&gt; 구믄은 고유의 데이타 레이스 컨디션 문제를 가지고 있습니다. 코드를 보는 것 만으로는 데이타 레이스 문제를 찾기가 쉽지 않습니다. 사실 이 데이타 레이스 문제는 다른 데이타 레이스 문제에 의해 유발되는데, 이러한 간단한 프로그램에도 벌써 4개의 데이타 레이스 문제가 존재 합니다! &lt;br /&gt;&lt;br /&gt;이 파티셔닝 프로그램에서의 4번째 데이타 레이스 문제는 설명하기 쉽습니다. 18번째 줄에서 각각의 쓰레드의 그룹 ID 는 루틴 매개 변수 &lt;B&gt;arg&lt;/B&gt; 에 의해 건네지고 이것은 메인 프로그램의 루프 인덱스 i 의 주소를 통해서 전달 됩니다. 메인 쓰레드 프로그램은 44번째 줄에서 루프 인덱서 i 까지 진행되고 &lt;B&gt;arg&lt;/B&gt; 에 의해 가르켜지는 메모리 장소에 새로운 값을 씁니다. 그러므로 이 메모리 장소를 읽고 작업 쓰레드가 이것을 그룹 ID 로 변환 하고 (18번째 줄), 메인 쓰레드에 의해 새로운 루프 인덱스 값이 쓰여지는(44번째 줄) 동안에 데이타 레이스 컨디션이 존재 합니다. &lt;br /&gt;&lt;br /&gt;이 데이타 레이스 컨디션이 발생되면 두개의 서로 다른 작업 쓰레드가 동일한 그룹 ID 로 지정되고 28번째 줄에서 데이타 레이스 컨디션을 유발할 것입니다. 그러나 이 두개의 데이타 레이스 컨디션의 진짜 원인은 45번과 18번째 줄의 올바르지 않은 코딩 스타일 때문입니다. 항상 데이타의 포인터 대신에 데이타 값을 전달해야 합니다. &lt;br /&gt;&lt;br /&gt;파티셔닝 프로그램을 OpenMP 를 이용해서 구현했다면 3번째와 4번째 데이타 레이스 컨디션은 발생하지 않았을 것입니다. OpenMP 같은 고수준의 프로그래밍 모델은 이러한 구현 버그들의 위험성을 줄여 줍니다. 만약 여러분의 멀티쓰레드 프로그램이 OpenMP 로 구현될 수 있다면 반드시 사용을 고려하시기 바랍니다. OpenMP 로 이 파티셔닝 프로그램을 구현했다면 좀 더 안전하고 효율 적이였을 것입니다.&lt;br /&gt;&lt;br /&gt;아래는 파티셔닝 프로그램을 OpenMP 로 구현한 것입니다. collect 루틴의 입력 매개변수 타입이 더이상 &lt;CODE&gt;void*&lt;/CODE&gt; 포인터 타입으로 제한되지 않음으로써 입력 매개변수를 정수 타입으로 정의하고 루프 인덱스 값을 메인 프로그램으로 부터 그룹 ID 로 취합니다. collect 루틴의 리턴 타입 또한 제한되지 않습니다. 리턴 값은 정수 타입으로 정의 되었고 취합된 그룹 카운트는 메인 프로그램이 리턴 됩니다. OpenMP 프로그램은 좀 더 안전하고 구현하기도 좀 더 쉽고 또한 Pthread 프로그램 보다 이해하기 쉽습니다.&lt;br /&gt;&lt;br /&gt;&lt;SPAN style=&quot;FONT-WEIGHT: bold; FONT-FAMILY: monospace&quot;&gt;partition_omp.cpp&lt;/SPAN&gt;&lt;br /&gt;&lt;br /&gt;
&lt;TABLE style=&quot;WIDTH: 90%; TEXT-ALIGN: left&quot; cellSpacing=2 cellPadding=2 border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD style=&quot;VERTICAL-ALIGN: top; BACKGROUND-COLOR: rgb(238,238,238)&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;1.&amp;nbsp; // global declaration&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;2.&amp;nbsp; #include &amp;lt;stdio.h&amp;gt;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;3.&amp;nbsp; #include &amp;lt;math.h&amp;gt;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;4.&amp;nbsp; #include &amp;lt;omp.h&amp;gt;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;5.&amp;nbsp; #include &quot;element.h&quot;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;6.&amp;nbsp; #include &quot;container.h&quot;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;7.&amp;nbsp; #define NGRPS 30&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;8.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;9.&amp;nbsp; int object_count = 0;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;10. element* object_array;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;11. container group_array[NGRPS];&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;12. int total_count = 0;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;13.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;14. int collect(int group_id) // return the collected group count&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;15. {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;16. &amp;nbsp;&amp;nbsp; int j;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;17. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;int group_count = 0;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;18. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;19. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;attribute group_attribute = get_group_attribute(group_id);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;20. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;container group_container = group_array[group_id];&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;21. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;for (j = 0; j &amp;lt; object_count; j++) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;22. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;element current_object = object_array[j];&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;23. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;if (current_object.collectFlag == true) continue; // this flag is initialized to false &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;24. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;if (current_object.matchAttribute( group_attribute)) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;25. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;current_object.collectFlag = true;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;26. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;group_container.add( current_object);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;27. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;group_count++; &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;28. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;}&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;29. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;}&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;30. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;return group_count;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;31. } &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;32. &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;33.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;34. int main(int argc, char** argv) &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;35. {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;36. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;int i;&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;37. #ifdef _OPENMP &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;38. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;omp_set_num_threads( NTHRS );&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;39. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;omp_set_dynamic(0);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;40. #endif&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;41.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;42. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;object_count = process_input_data(argv[1], &amp;amp;object_array);&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;43.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;44. #pragma omp parallel for &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;45. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;for (i = 0; i &amp;lt; NTHRS; i++) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;46. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;total_count += collect( i );&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;47. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;} &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;48.&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;49. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;if (total_count != object_count) {&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;50. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;printf(&quot; the collected object count %d doesn&#039;t match the original object count %d\n&quot;,&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;50. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;total_count, object_count); &lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;51. &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;}&lt;/SPAN&gt;&lt;BR style=&quot;FONT-FAMILY: monospace&quot;&gt;&lt;SPAN style=&quot;FONT-FAMILY: monospace&quot;&gt;52. }&lt;/SPAN&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;br /&gt;
&lt;H2&gt;&lt;FONT size=3&gt;요약&lt;/FONT&gt;&lt;/H2&gt;
&lt;P&gt;병렬 프로그램은 대부분의 소프트웨어 개발자에게 새로운 세계 입니다. 현재의 처리량(throughput) 컴퓨팅 트렌드의 멀티-코어 프로세스 기술은 많은 소프트웨어 개발자들이 병렬 프로그래밍을 강요하고 있습니다. 운나쁘게도 병렬 소프트웨어 개발의 어려움은 순차적인 소프트웨어 개발 보다 몇단계 더 어렵습니다. 병렬 프로그래밍에는 더 다양한 디자인 이슈들이 존재 합니다. 그럼에도 불구하고 레이스 컨디션은 개발자가 접하는 가장 기본적인 문제입니다. 이 글에서 우리는 개발자가 배워야할 그리고 병렬 소프트웨어 디자인시에 피해야할 다양한 레이스 컨디션 이슈들에 대해 다루었습니다. &lt;br /&gt;&lt;br /&gt;소프트웨어 개발은 적절한 툴의 셋을 사용할 것을 요구 합니다. 그리고 병렬 소프트웨어서는 특히 더 그렇습니다. 이 글에서의 병렬 프로그램 분석을 통해서 툴이 레이스 컨디션을 쉽게 찾아낼 수 있는 툴이 필요한지를 잘 알 수 있습니다. 아직 까지는 일반적인 레이스 컨디션을 다룰 수 있는 개발자 툴이 존재하지는 않습니다. 그리고 복잡한 프로그램의 특성상 이러한 툴이 존재할 수 있는지에 대해서도 의문 입니다. 그러므로 많은 컴퓨터 과학 연구자들은 트랜젝션적인 메모리 접근을 지지하고 있습니다.&lt;br /&gt;&lt;br /&gt;어쨌든 데이타 레이스 컨디션 문제를 다루기 위한 몇가지 툴들이 현재 존재 합니다. 썬이 배포하고 있는 썬 스튜디오 익스프레스의 데이타 레이스 감지 툴 이 바로 그러한 툴이고 인텔의 쓰레드 체커, 오픈소스 Valgrind 의 Helgrind 등이 바로 그것입니다.&lt;br /&gt;&lt;br /&gt;훌륭한 질의 소프트웨어를 디자인하는 것은 절대적으로 프로그램의 지식과 경험에 달려 있고 또한 적절한 툴 사용에도 잘려 있습니다. 레이스 컨디션 문제들을 회피할 수 있는 레슨들이 몇가지 있는데 아래에 이러한 것들이 요약 되어 있습니다: 
&lt;UL&gt;
&lt;LI&gt;레이스 컨디션을 유발하는 장황한 구현의 위험을 줄여줄 수 있는 OpenMP 같은 고급 디자인 추상 모델을 수용한다. 
&lt;LI&gt;포인터에의한전달 대신 데이타값에의한전달을 이용하여 쓰레드와 프로세스들 간 통신하기. 
&lt;LI&gt;글로벌 변수의 사용을 제한하는 데이타구조 디자인 및 복수개 쓰레드의 공유 변수 접근 금지하기. 
&lt;LI&gt;프로그램 상태 및 입력 셋, 런타임 환경을 분석하여 레이스 컨디션이 실제 프로그램 버그인지를 확인하기. 이러한 방법을 통해 더 나은 퍼포먼스를 얻을 수 있음. 
&lt;LI&gt;레이스 컨디션의 실제 원인을 분석. 레이스 컨디션의 해결 대신에 실제 프로그램 버그의 수정에 집중함. 
&lt;LI&gt;프로그램의 실행 상태와 상태 전환에 대해 완전히 이해 하기. 쓰레드 혹은 프로세스가 몇몇 프로그램 오브젝트에 의해 상태 전환이 유발될때, 다른 병행 쓰레드 혹은 프로세스가 동일한 오브젝트에 병렬로 접근하는 것을 방지함. 
&lt;LI&gt;프로그램의 각각의 작업 단계마다 프로그램의 상태 무결성을 확인할 수 있는 내부 상태 체크 메카니즘을 구현. &lt;/LI&gt;&lt;/UL&gt;
&lt;H2&gt;&lt;FONT size=3&gt;&lt;br /&gt;참고자료&lt;/FONT&gt; &lt;/H2&gt;
&lt;OL&gt;
&lt;LI&gt;&quot;Parallel Programming Introduction&quot;, &lt;A href=&quot;http://www.mhpcc.edu/training/workshop/parallel_intro/MAIN.html&quot;&gt;http://www.mhpcc.edu/training/workshop/parallel_intro/MAIN.html&lt;/A&gt; 
&lt;LI&gt;&quot;POSIX Threads Programming&quot;, &lt;A href=&quot;http://www.llnl.gov/computing/tutorials/pthreads&quot;&gt;http://www.llnl.gov/computing/tutorials/pthreads&lt;/A&gt; 
&lt;LI&gt;&quot;OpenMP home page&quot;, &lt;A href=&quot;http://www.openmp.org/&quot;&gt;http://www.openmp.org&lt;/A&gt; 
&lt;LI&gt;&quot;The Message Passing Interface (MPI) standard&quot;, &lt;A href=&quot;http://www-unix.mcs.anl.gov/mpi/&quot;&gt;http://www-unix.mcs.anl.gov/mpi/&lt;/A&gt; 
&lt;LI&gt;&quot;Open MPI: Open Source High Performance Computing&quot;,&lt;A href=&quot;http://www.open-mpi.org/&quot;&gt;http://www.open-mpi.org/&lt;/A&gt; 
&lt;LI&gt;&quot;What are Race Conditions? Some Issues and Formalization&quot;, Robert H.B. Netzer and Barton P. Miller, In ACM Letters on Programming Languages and Systems, Vol. 1 No. 1 March 1992 
&lt;LI&gt;&quot;Transactional Memory Online&quot;, &lt;A href=&quot;http://www.cs.wisc.edu/trans-memory/&quot;&gt;http://www.cs.wisc.edu/trans-memory/&lt;/A&gt; 
&lt;LI&gt;&quot;Transactional Memory Coherence and Consistence&quot;, Lance Hammond, Vicky Wong, Mike Chen, Brian D. Carlstrom, John D. Davis, Ben Hertzberg, Manohar K. Prahu, Honggo Wijaya, Christos Kozyrakis and Kunle Olukotun, &lt;A href=&quot;http://ogun.stanford.edu/%7Ekunle/publications/tcc_stmcs2006.pdf&quot;&gt;http://ogun.stanford.edu/~kunle/publications/tcc_stmcs2006.pdf&lt;/A&gt; 
&lt;LI&gt;&quot;OpenMP Parallelization Pragmas for C and C++&quot;, &lt;A href=&quot;http://www.tacc.utexas.edu/services/userguides/pgi/pgiws_ug/pgi32u12.htm&quot;&gt;http://www.tacc.utexas.edu/services/userguides/pgi/pgiws_ug/pgi32u12.htm&lt;/A&gt; 
&lt;LI&gt;&quot;Throughput Computing Main Page&quot;, &lt;A href=&quot;http://www.sun.com/processors/throughput/&quot;&gt;http://www.sun.com/processors/throughput/&lt;/A&gt; 
&lt;LI&gt;&quot;Developing Applications For Parallel Computing&quot;, Liang T. Chen, &lt;A href=&quot;file:///C:/solaris/articles/parallel.html&quot;&gt;http://developers.sun.com/solaris/articles/parallel.html&lt;/A&gt; 
&lt;LI&gt;&quot;Sun Studio Express: Data Race Detection Tool&quot;, &lt;A href=&quot;file:///C:/sunstudio/downloads/drdt/drdt_index.html&quot;&gt;http://developers.sun.com/sunstudio/downloads/drdt/drdt_index.html&lt;/A&gt; 
&lt;LI&gt;&quot;Intel Threading Tools&quot;,&lt;A href=&quot;http://www.intel.com/cd/software/products/asmo-na/eng/threading/tcwin/index.htm&quot;&gt;http://www.intel.com/cd/software/products/asmo-na/eng/threading/tcwin/index.htm&lt;/A&gt; 
&lt;LI&gt;&quot;Valgrind&#039;s Tool Suite&quot;, &lt;A href=&quot;http://valgrind.org/info/tools.html&quot;&gt;http://valgrind.org/info/tools.html&lt;/A&gt; &lt;/LI&gt;&lt;/OL&gt;
&lt;DIV&gt;&lt;br /&gt;
&lt;H2&gt;&lt;FONT size=3&gt;감사의 인사&lt;/FONT&gt; &lt;/H2&gt;
&lt;P&gt;필자는 이 글에 영감을 준 데이타 레이스 감지 툴 프로젝트에 참여하고있는 같은 썬 동료들에게 감사의 인사를 전합니다. 이글에서 언급된 몇몇 데이타 레이스 컨디션들은 DRDT 테스팅에서 발견된 실제 문제들에서 취해졌습니다. 또한 초기 드래프트를 리뷰해준 아들 David Chen 과 썬 동료들 Yuan Lin 과 Vijay Tatkar 에게 감사의 인사를 전합니다. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;이 글의 영문 원본은&lt;br /&gt;&lt;A href=&quot;http://developers.sun.com/solaris/articles/raceconditions.html&quot; target=_blank&gt;The Challenge of Race Conditions in Parallel Programming&lt;br /&gt;&lt;/A&gt;에서 보실 수 있습니다.&lt;br /&gt;&lt;/P&gt;&lt;/DIV&gt;&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이센스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=_blank&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=_blank&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div id=&quot;variety_topic&quot; class=&quot;widget&quot;&gt;
	&lt;h3&gt;다양한 이야깃거리&lt;/h3&gt;&lt;div id=&quot;category_related&quot; class=&quot;widget&quot;&gt;
		&lt;h4&gt;카테고리 관련글&lt;/h4&gt;
		&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/643&quot; title=&quot;병렬프로그래밍에서 레이스 컨디션에 대처하기&quot;&gt;병렬프로그래밍에서 레이스 컨디션에 대처하기&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/21&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/628&quot; title=&quot;솔라리스상에서 PHP 를 이용한 웹 어플리케이션 작성&quot;&gt;솔라리스상에서 PHP 를 이용한 웹 어플리케이션 작성&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/07/23&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/599&quot; title=&quot;원자적인 SPARC: SPARC 의 원자적 연산들 사용하기&quot;&gt;원자적인 SPARC: SPARC 의 원자적 연산들...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/06/20&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/571&quot; title=&quot;dbx 를 이용해서 JVM 레벨의 hang 디버깅 하기&quot;&gt;dbx 를 이용해서 JVM 레벨의 hang 디버깅 하기&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/06/11&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/545&quot; title=&quot;스토리지 유틸리티 실습: ZFS 스냅샷과 Amazon S3 연동&quot;&gt;스토리지 유틸리티 실습: ZFS 스냅샷과 Amaz...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/05/23&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;
		&lt;/div&gt;&lt;/div&gt;</description>
			<category>개발자코너</category>
			<category>General Race Condition</category>
			<category>OpenMP</category>
			<category>Parallel</category>
			<category>Parallel Programming</category>
			<category>Pthreads</category>
			<category>Race Condition</category>
			<category>Race Conditions</category>
			<category>데이타 레이스 컨디션</category>
			<category>레이스 컨디션</category>
			<category>병렬 소프트웨어</category>
			<category>병렬 프로그래밍</category>
			<category>파티셔닝</category>
			<category>파티셔닝 프로그램</category>
			<author>(SDNKorea)</author>
			<guid>http://sdnkorea.com/blog/643</guid>
			<comments>http://sdnkorea.com/blog/643#entry643comment</comments>
			<pubDate>Tue, 19 Aug 2008 20:42:23 +0900</pubDate>
		</item>
		<item>
			<title>플래시 어카이브로 부터 솔라리스10 Branded 존 설치하기</title>
			<link>http://sdnkorea.com/blog/639</link>
			<description>&lt;P&gt;branded 존은 솔라리스 운영체제의 다른 버전을 실행할 수 있는 존입니다. 솔라리스8, 솔라리스9 branded 존의 소개로 인해서 기존의 설치환경을 존으로 옮기는 것이 매우 쉬워졌습니다. 단순히 설치본의 플래시 어카이브를 생성하고 branded 존을 생성한다음 플래시 어카이브를 이용해서 존에 OS 를 설치 하면 됩니다.&lt;/P&gt;
&lt;P&gt;그러나 솔라리스10 존을 설치하기 위해 사용되는 네이티브 brand 에서는 이러한 기능을 지원하지 않습니다. 이 기능은 만약 현존하는 솔라리스10 설치본을 다른 하드웨어로 옮길때 매우 유용할 것입니다. 존안에 새로운 솔라리스10 배포판 사용을 원할때도 유용할 수 있습니다.&lt;/P&gt;
&lt;P&gt;이 글은 솔라리스10 존을 플래시 어카이브를 통해서 설치하기 위해 솔라리스10 brand 를 생성하는 방법을 설명하고 있으며 다음과 같은 주제들을 다루고 있습니다:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href=&quot;http://www.sdnkorea.com/blog/639#1&quot;&gt;branded 존 파일&lt;/A&gt; 
&lt;LI&gt;&lt;A href=&quot;http://www.sdnkorea.com/blog/639#2&quot;&gt;솔라리스10 brand 빌드하기&lt;/A&gt; 
&lt;LI&gt;&lt;A href=&quot;http://www.sdnkorea.com/blog/639#3&quot;&gt;branded 존 생성 및 설치하기&lt;/A&gt; 
&lt;LI&gt;&lt;A href=&quot;http://www.sdnkorea.com/blog/639#4&quot;&gt;존의 오류 서비스들을 복구하기&lt;/A&gt; 
&lt;LI&gt;&lt;A href=&quot;http://www.sdnkorea.com/blog/639#5&quot;&gt;오류 서비스 해결책 자동화 하기&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;H3&gt;&lt;A name=1&gt;&lt;FONT size=3&gt;&lt;br /&gt;branded 존 파일&lt;/FONT&gt;&lt;/A&gt;&lt;/H3&gt;
&lt;P&gt;현재 두가지의 brand 가 존재 합니다: 솔라리스8 brand 와 솔라리스9 brand.&lt;/P&gt;
&lt;P&gt;솔라리스9 브랜드는 솔라리스10 brand 를 생성하기 위해 사용되는 템플릿으로 이용되는 네이티브 brand 와 합쳐져 있습니다. 네이티브 brand 에 대해 먼저 살펴 봅시다.&lt;/P&gt;
&lt;P&gt;네이티브 brand 의 위치는 다음과 같습니다:&lt;/P&gt;&lt;PRE class=small&gt;/usr/lib/brand/native
&lt;/PRE&gt;
&lt;P&gt;이 데렉토리는 3가지 파일을 가지고 있습니다:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE class=small&gt;config.xml&lt;/CODE&gt; 은 설치, 검사, 부팅, 존의 권한을 설정하기 위한 모든 정보를 포함하고 있습니다 
&lt;LI&gt;&lt;CODE class=small&gt;platform.xml&lt;/CODE&gt; 은 디바이스와 존의 마운트를 위한 정보를 포함하고 있습니다 
&lt;LI&gt;&lt;CODE class=small&gt;postclone&lt;/CODE&gt; 은 존의 클로닝 이후에 수행되어야할 작업들의 정보를 포함하고 있습니다 &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;솔라리스9 brand 는 조금 더 복잡합니다. 위치는 다음과 같습니다:&lt;/P&gt;&lt;PRE class=small&gt;/usr/lib/brand/Solaris9
&lt;/PRE&gt;
&lt;P&gt;이 디렉토리는 네이티브 존의 디렉토리와 동일한 파일들을 포함하고 있습니다. 그러나 다음의 파일들 또한 특수한 용도를 위해 포함하고 있습니다:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE class=small&gt;s9_install&lt;/CODE&gt;. 이 스크립트는 시스템을 어떻게 설치할지와 &lt;CODE class=small&gt;s9_p2v&lt;/CODE&gt; 파일의 위치를 지정하고 있습니다. 
&lt;LI&gt;&lt;CODE class=small&gt;s9_p2v&lt;/CODE&gt;. 이 스크립트는 정보의 후처리방법을 담고 있습니다. 가장 중요한 기능은 수정될 파일들의 위치와 &lt;CODE class=small&gt;s9_system&lt;/CODE&gt; 파일의 위치 입니다. 
&lt;LI&gt;&lt;CODE class=small&gt;s9_servicetag&lt;/CODE&gt;. 이 스크립트는 &lt;CODE class=small&gt;servicetag&lt;/CODE&gt; 를 존에 추가 합니다. 이 파일은 &lt;CODE class=small&gt;s9_install&lt;/CODE&gt; 파일에 의해 참조 됩니다. 
&lt;LI&gt;&lt;CODE class=small&gt;s9_support&lt;/CODE&gt;. 이 바이너리는 &lt;CODE class=small&gt;zonecfg verify&lt;/CODE&gt; 서브커맨드에 의해 사용되며 존의 설정을 검사 합니다. 
&lt;LI&gt;&lt;CODE class=small&gt;s9_system&lt;/CODE&gt;. 이 스크립트는 새로운 존의 &lt;CODE class=small&gt;/etc/default/system&lt;/CODE&gt; 파일을 수정합니다. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;솔라리스9 brand 는 또한 다음의 서브디렉토리들을 포함하고 있습니다:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE class=small&gt;files/patches&lt;/CODE&gt;. 이 디렉토리는 &lt;CODE class=small&gt;order&lt;/CODE&gt; 파일을 포함하고 있는 데 이 파일은 어떠한 패치들이 설치되어야 하는지에 대한 순서를 설명합니다. 실제 패치들은 &lt;CODE class=small&gt;files/patches&lt;/CODE&gt; 에 또한 존재 합니다. 
&lt;LI&gt;&lt;CODE class=small&gt;mods&lt;/CODE&gt;. 이 디렉토리는 설치후 수정작업들을 포함하고 있습니다. &lt;CODE class=small&gt;s9_p2v&lt;/CODE&gt; 스크립트는 이 디렉토리에 나타난 순서대로 하나씩하나씩 수정을 가합니다. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;파일에 특수한 용도가 있는 것인지는 &lt;CODE class=small&gt;s9_install&lt;/CODE&gt; 파일을 살펴 봄으로써 알아볼 수 있습니다. 이 파일은 &lt;CODE class=small&gt;config.xml&lt;/CODE&gt;, 에 의해 정의도고 존 설치시에 사용 됩니다. 모든 파일들은 &lt;CODE class=small&gt;s9_install&lt;/CODE&gt; 에서 참조된 모든 파일들이 포함되고 또한 참조 파일들에 의해서 참조되는 모든 파일들 또한 포함됩니다. 참조 트리는 그림 1 과 같이 적용 됩니다.&lt;/P&gt;
&lt;P align=center&gt;&lt;I&gt;&lt;B class=small&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://sdnkorea.com/blog/attach/1/1083488313.gif&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;199&quot; width=&quot;500&quot; /&gt;&lt;/div&gt;그림 1: 참조 트리&lt;/B&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P&gt;또한 &lt;CODE class=small&gt;s9_support&lt;/CODE&gt; 파일도 포함 됩니다. 왜냐하면 이것은 존의 설정 검사를 위해 사용되기 때문입니다. 만약 솔라리스10 branded 존을 &lt;CODE class=small&gt;pkg-inherit-dir&lt;/CODE&gt; 변수를 이용해 설정하려고 한다면 에러를 돌려 줍니다. 이 파일은 &lt;CODE class=small&gt;config.xml&lt;/CODE&gt; 에서 참조 됩니다 (&lt;A href=&quot;http://www.sdnkorea.com/blog/639#2&quot;&gt;솔라리스10 brand 빌드하기&lt;/A&gt;&amp;nbsp;섹션을 참조하시기 바랍니다).&lt;/P&gt;
&lt;H3&gt;&lt;A name=2&gt;&lt;FONT size=3&gt;&lt;br /&gt;솔라리스10 brand 빌드하기&lt;/FONT&gt;&lt;/A&gt;&lt;/H3&gt;
&lt;P&gt;이제 특수한 파일들과 디렉토리들이 식별되었고, 여러분은 솔라리스10 brand 를 빌드하실 수 있습니다.&lt;/P&gt;
&lt;P&gt;1. 디렉토리 구조 생성하기:&lt;/P&gt;&lt;PRE class=small&gt;/usr/lib/brand/solaris10
/usr/lib/brand/solaris10/mods
/usr/lib/brand/solaris10/files
/usr/lib/brand/solaris10/files/patches
&lt;/PRE&gt;
&lt;P&gt;2. 표 1에서 나온 대로 네이티브 brand 와 솔라리스9 brand 에서 파일들을 복사하기 (경로들은 &lt;CODE class=small&gt;/usr/lib/brand/&lt;/CODE&gt; 로 부터 상대적임)&lt;/P&gt;&lt;!-- BEGIN G1 FEATURED CONTENT COMPONENT, VARIATION 1 --&gt;
&lt;TABLE cellSpacing=0 cellPadding=0 width=&quot;100%&quot; border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=tablecaption&gt;
&lt;DIV class=headerpadding&gt;표 1: 솔라리스10 brand 를 생성하기 위한 소스와 목적지 파일들&lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;
&lt;TABLE class=dkgrey1 cellSpacing=0 cellPadding=0 width=&quot;100%&quot; border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;
&lt;TABLE class=vatop cellSpacing=1 cellPadding=0 width=&quot;100%&quot; summary=&quot;placeholder summary&quot; border=0&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TH class=columncaption id=bzf_source&gt;
&lt;DIV class=headerpadding&gt;소스&lt;/DIV&gt;&lt;/TH&gt;
&lt;TH class=columncaption id=bzf_dest&gt;
&lt;DIV class=headerpadding&gt;목적지&lt;/DIV&gt;&lt;/TH&gt;&lt;/TR&gt;
&lt;TR class=yellow1&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;native/config.xml&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/config.xml&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow2&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;native/platform.xml&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/platform.xml&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow1&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;native/postclone&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/postclone&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow2&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris9/s9_install&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/s10_install&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow1&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris9/s9_servicetag&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/s10_servicetag&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow2&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris9/s9_p2v&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/s10_p2v&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow1&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris9/s9_system&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/s10_system&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow2&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris9/mods/S20_install_patches&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/mods/S20_install_patches&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow1&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris9/mods/S3*_*&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/mods/S3*_*&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR class=yellow2&gt;
&lt;TD headers=bzf_source&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris9/files/patches/order&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;
&lt;TD headers=bzf_dest&gt;
&lt;DIV class=pad5x10&gt;&lt;CODE class=small&gt;solaris10/files/patches/order&lt;/CODE&gt; &lt;/DIV&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;SPAN class=sp10&gt;&amp;nbsp;&lt;/SPAN&gt; &lt;!-- END G1 FEATURED CONTENT COMPONENT, VARIATION 1 --&gt;
&lt;P&gt;3. 다음 파일들의 정보를 수정하기:&lt;/P&gt;
&lt;P&gt;a. &lt;CODE class=small&gt;config.xml&lt;/CODE&gt; 에서:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE class=small&gt;brand name=native&lt;/CODE&gt; 을 &lt;CODE class=small&gt;brand name=solaris10&lt;/CODE&gt; 으로 교체 
&lt;LI&gt;&lt;CODE class=small&gt;&amp;lt;install&amp;gt;/usr/lib/lu/lucreatezone -z %z&amp;lt;/install&amp;gt;&lt;/CODE&gt; 을 &lt;CODE class=small&gt;&amp;lt;install&amp;gt;/usr/lib/brand/solaris10/s10_install %z %R %*&amp;lt;/install&amp;gt;&lt;/CODE&gt; 로 교체 
&lt;LI&gt;&lt;CODE class=small&gt;&amp;lt;installopts&amp;gt;&amp;lt;/installopts&amp;gt;&lt;/CODE&gt; 을 &lt;CODE class=small&gt;&amp;lt;installopts&amp;gt;a:d:DhpsuvV&amp;lt;/installopts&amp;gt;&lt;/CODE&gt; 로 교체. 
&lt;LI&gt;&lt;CODE class=small&gt;&amp;lt;verify_cfg&amp;gt;&amp;lt;/verify_cfg&amp;gt;&lt;/CODE&gt; 을 &lt;CODE class=small&gt;&amp;lt;verify_cfg&amp;gt;/usr/lib/brand/solaris10/s10_support verify&amp;lt;/verify_cfg&amp;gt;&lt;/CODE&gt; 로 교체. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;b. &lt;CODE class=small&gt;platform.xml&lt;/CODE&gt; 에서 아래 라인을 추가 함으로써 &lt;CODE class=small&gt;/usr&lt;/CODE&gt; 파일 시스템의 루프백 마운트를 위한 (이후의 수정사항을 적용하기 위해 필요함) 추가 항목을 생성 합니다.:&lt;/P&gt;&lt;PRE class=small&gt;&amp;lt;global_mount special=&quot;/usr&quot; directory=&quot;/.SUNWnative/usr&quot; \
type=&quot;lofs&quot; opt=&quot;ro,nodevices&quot; /&amp;gt;
&lt;/PRE&gt;
&lt;P&gt;c. &lt;CODE class=small&gt;s10_install&lt;/CODE&gt;, &lt;CODE class=small&gt;s10_servicetag&lt;/CODE&gt; 그리고 &lt;CODE class=small&gt;s10_system&lt;/CODE&gt; 파일에 존재하는 모든 &lt;CODE class=small&gt;Solaris9&lt;/CODE&gt; 과 &lt;CODE class=small&gt;s9&lt;/CODE&gt; 을 각각 &lt;CODE class=small&gt;Solaris10&lt;/CODE&gt; 과 &lt;CODE class=small&gt;s10&lt;/CODE&gt; 으로 변경합니다.&lt;/P&gt;
&lt;P&gt;d. &lt;CODE class=small&gt;s10_p2v&lt;/CODE&gt; 에서:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;모든 &lt;CODE class=small&gt;Solaris9&lt;/CODE&gt; 과 &lt;CODE class=small&gt;s9&lt;/CODE&gt; 을 각각 &lt;CODE class=small&gt;Solaris10&lt;/CODE&gt; 과 &lt;CODE class=small&gt;s10&lt;/CODE&gt; 으로 변경합니다. 
&lt;LI&gt;&lt;CODE class=small&gt;s9_preload.so.1&lt;/CODE&gt; 라이브러리와 관련된 항목들을 커멘트 처리 합니다. 왜냐하면 이 라이브러리는 솔라리스10 에 필요하지 않기 때문입니다. &lt;/LI&gt;&lt;/UL&gt;
&lt;H3&gt;&lt;A name=3&gt;&lt;FONT size=3&gt;&lt;br /&gt;branded 존 생성 및 설치하기&lt;/FONT&gt;&lt;/A&gt;&lt;/H3&gt;
&lt;P&gt;이제 brand 가 생성되었고 솔라리스10 branded 존 설정이 가능합니다:&lt;/P&gt;&lt;PRE class=small&gt;zonecfg -z 10_zone01
	create
	set autoboot=true
	set zonepath=/export/zones/solaris10/zone01
	set brand=solaris10
	add net
		set physical=hme0
		set address=10.0.0.1/24
	end
	remove inherit-pkg-dir
	verify
	commit
&lt;/PRE&gt;
&lt;P&gt;설정된 존은 이제 플래시 어카이브(&lt;CODE class=small&gt;/tmp/solaris10.flar&lt;/CODE&gt;) 를 이용해서 설치 가능합니다:&lt;/P&gt;&lt;PRE class=small&gt;zoneadm -z 10_zone01 install -p -a /tmp/solaris10.flar
&lt;/PRE&gt;
&lt;P&gt;15분 정도의 작업 후에 존은 사용될 준비가 되었습니다.&lt;/P&gt;
&lt;H3&gt;&lt;A name=4&gt;&lt;FONT size=3&gt;&lt;br /&gt;존의 오류 서비스들을 복구하기&lt;/FONT&gt;&lt;/A&gt;&lt;/H3&gt;
&lt;P&gt;존이 처음 부팅될때는 유지보수 모드(maintenance mode) 로 부팅될 것이고 몇몇 서비스들은 정상적으로 시작되지 않을 것입니다. 이것은 몇몇 서비스들이 존에서 실행이 불가능함으로써 발생되는 현상 입니다. 이러한 서비스들을 제거하고 머신을 제거함으로서 의존성을 해결할 수 있습니다.&lt;/P&gt;
&lt;P&gt;이 방법은 물론 빠르지만 약간 지저분한 방법입니다. 진짜로 해야 할 일은 &lt;CODE class=small&gt;p2v&lt;/CODE&gt; 수정을 작성함으로써 인스톨 후 과정에서 서비스들과 의존성들을 제거하는 것입니다.&lt;/P&gt;
&lt;P&gt;이 글에서 사용된 솔라리스10 플래시 어카이브는 설치에 필요한 최소의 어카이브 입니다 (&lt;CODE class=small&gt;SUNWCreq&lt;/CODE&gt; 클러스터). 대형 클러스터 환경에서는 서비스들이 완벽하지 않을 것입니다. 어쨌든 이러한 것을 다루는 방법은 동일 합니다.&lt;/P&gt;
&lt;P&gt;존에서 실행되지 않는 서비스들의 목록은 플래시 어카이브를 통해 설치된 존에서 사용가능한 서비스들의 목록과 네이티브 존에서 실행되는 서비스들의 목록을 비교하여 만들어 졌습니다. 다음의 서비스들은 존 내부에서 실행되지 않습니다. 왜냐하면 플래시로 설치된 존에서는 존재하지만 네이티브 존에서는 존재하지 않기 때문입니다:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE class=small&gt;svc:/network/nfs/server&lt;/CODE&gt; 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/dumpadm&lt;/CODE&gt; 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/scheduler&lt;/CODE&gt; 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/sysevent&lt;/CODE&gt; 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/picl&lt;/CODE&gt; 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/fmd&lt;/CODE&gt; 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/device/fc-fabric&lt;/CODE&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;각각의 서비스들을 위해서 의존성들이 해결되어야 합니다. 다음의 예는 &lt;CODE class=small&gt;sysevent&lt;/CODE&gt; 서비스의 의존성을 다룹니다.&lt;/P&gt;
&lt;P&gt;&lt;CODE class=small&gt;svcs -D&lt;/CODE&gt; 를 이용해서 어떠한 서비스들이 &lt;CODE class=small&gt;sysevent&lt;/CODE&gt; 서비스에 의존하고 있는지 확인합니다:&lt;/P&gt;&lt;PRE class=small&gt;bash-3.00# svcs -D sysevent
STATE      STIME    FMRI
online     Mar_11   svc:/system/device/fc-fabric:default
online     Mar_11   svc:/milestone/single-user:default
online     Mar_11   svc:/system/fmd:default
&lt;/PRE&gt;
&lt;P&gt;각각의 의존 서비스들은 속성들을 확인해서 서비스 디스크립터에서 의존성을 제거할 수 있는지 확인 합니다:&lt;/P&gt;&lt;PRE class=small&gt;bash-3.00# svccfg -s fc-fabric listprop
sysevent              dependency
sysevent/entities     fmri     svc:/system/sysevent
sysevent/grouping     astring  require_all
sysevent/restart_on   astring  none
sysevent/type         astring  service
---output truncated---
&lt;/PRE&gt;
&lt;P&gt;그림 2의 의존성 트리는 현재의 상황에서 적용 가능합니다.&lt;/P&gt;
&lt;P align=center&gt;&lt;I&gt;&lt;B class=small&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://sdnkorea.com/blog/attach/1/1098212522.gif&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;275&quot; width=&quot;500&quot; /&gt;&lt;/div&gt;그림 2: 의존성 트리&lt;/B&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P&gt;이제 우리들은 의존성들을 지우고 서비스들을 비활성화해야 합니다, 그리고 낮은 수준에서 높은 수준 순으로 작업해야 합니다. 그림 3의 흐름도는 과정을 보여주고 있습니다.&lt;/P&gt;
&lt;P align=center&gt;&lt;I&gt;&lt;B class=small&gt;&lt;div class=&quot;imageblock center&quot; style=&quot;text-align: center; clear: both;&quot;&gt;&lt;img src=&quot;http://sdnkorea.com/blog/attach/1/1319554505.gif&quot; alt=&quot;사용자 삽입 이미지&quot; height=&quot;439&quot; width=&quot;388&quot; /&gt;&lt;/div&gt;그림 3: 흐름도 &lt;/B&gt;&lt;/I&gt;&lt;/P&gt;
&lt;P&gt;이 흐름도와 &lt;CODE class=small&gt;sysevent&lt;/CODE&gt; 서비스의 의존성 트리를 이용해서 여러분은 서비스들을 트리의 낮은 수준의 서비스 부터 시작해서 수정 할 수 있고 이런 경우 &lt;CODE class=small&gt;milestone/devices&lt;/CODE&gt; 가 가장 낮은 수준의 서비스 입니다. &lt;/P&gt;
&lt;P&gt;다음의 목록에서 번호들은 흐름도에서 물어진 질문 들입니다. 의존성을 제거하기 위해서 &lt;CODE class=small&gt;svccfg -s &amp;lt;FMRI&amp;gt; delpg &amp;lt;property_group&amp;gt;&lt;/CODE&gt; 커맨드를 이용하는데 여기서 &lt;CODE class=small&gt;&amp;lt;FMRI&amp;gt;&lt;/CODE&gt; 는 오류 관리 리소스 인식자(fault management resource identifier&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;CODE class=small&gt;svc:/milestone/devices&lt;/CODE&gt;: 1: yes; 2: yes; 의존성을 제거 (devices property group). 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/device/fc-fabric&lt;/CODE&gt;: 1: no; 서비스를 제거. 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/milestone/single-user&lt;/CODE&gt;: 1: yes; 2: yes; 의존성을 제거 (syseventd_single-user property group). 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/fmd&lt;/CODE&gt;: 1: no; 서비스를 제거. 
&lt;LI&gt;&lt;CODE class=small&gt;svc:/system/sysevent&lt;/CODE&gt;: 1: no; 서비스를 제거. 이제 이것은 올바른 작업입니다. 왜냐하면 모든 의존성들이 제거 되었기 때문입니다. 또한 이것이 하위 레벨부터 상위레벨 순으로 작업해야 하는 이유 이기도 합니다. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;존에서 실행되지 않는 서비스들에 차례대로 위와 같은 흐름도를 적용 합니다. 몇몇 중첩된 사항들이 존재하기도 합니다. 예를 들어 &lt;CODE class=small&gt;fc-fabric&lt;/CODE&gt; 서비스는 &lt;CODE class=small&gt;sysevent&lt;/CODE&gt;을 처음으로 수정했다면 이미 삭제되었을 것입니다. 삭제된 모든 서비스들과 서비스의 속성들을 반드시 로그로 남기시기 바랍니다.&lt;/P&gt;
&lt;H3&gt;&lt;A name=5&gt;&lt;FONT size=3&gt;&lt;br /&gt;오류 서비스 해결책 자동화 하기&lt;/FONT&gt;&lt;/A&gt;&lt;/H3&gt;
&lt;P&gt;마지막으로 해야할 일은 &lt;A href=&quot;http://www.sdnkorea.com/blog/639#4&quot;&gt;존의 오류 서비스들을 복구하기&lt;/A&gt; 에서 기술된 해결책을 자동화 하는 것입니다. 이것을 위해서 &lt;CODE class=small&gt;S40_fix_services&lt;/CODE&gt; 스크립트를 만들고 이것을 솔라리스10 brand 의 &lt;CODE class=small&gt;mods&lt;/CODE&gt; 디렉토리에 넣습니다. 기본적으로 여러분은 위의 섹션에서 만들어 놓은 기록들을 이용해서 스크립트를 생성할 수 있습니다.&lt;/P&gt;
&lt;P&gt;이 스크립트는 최소한 다음의 두가지 기능을 가지고 있어야 합니다:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;지정된 서비스의 지정된 속성 값 삭제 
&lt;LI&gt;서비스 삭제 &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;대안으로 여러분은 삭제 대신에 서비스를 비활성화 할 수도 있습니다. 물론 삭제가 선호되기는 하는데 왜냐하면 어쨌든 서비스들은 실행되지 못할 것이기 때문입니다.&lt;/P&gt;
&lt;P&gt;스크립트가 완성된 다음에는 존의 재설치 후에 시스템이 정상적으로 부팅 될 것입니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;이 글의 영문 원본은&lt;br /&gt;&lt;A href=&quot;http://www.sun.com/bigadmin/content/submitted/branded_zones_flash.jsp&quot; target=_blank&gt;Installing Solaris 10 Branded Zones From a Flash Archive&lt;/A&gt;&lt;br /&gt;에서 보실 수 있습니다.&lt;/P&gt;&lt;!-- END CUSTOM CONTENT --&gt;&lt;!-- END WIKI LINK --&gt;&lt;!-- License --&gt;&lt;fieldset style=&quot;margin:20px 0px 20px 0px;padding:5px;&quot;&gt;&lt;legend&gt;&lt;span&gt;&lt;strong&gt;크리에이티브 커먼즈 라이센스&lt;/strong&gt;&lt;/span&gt;&lt;/legend&gt;&lt;!--Creative Commons License--&gt;&lt;div style=&quot;float: left; width: 88px; margin-top: 3px;&quot;&gt;&lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=_blank&gt;&lt;img alt=&quot;Creative Commons License&quot; style=&quot;border-width: 0&quot; src=&quot;http://i.creativecommons.org/l/by-nc-nd/2.0/kr/88x31.png&quot;/&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style=&quot;margin-left: 92px; margin-top: 3px; text-align: justify;&quot;&gt;이 저작물은 &lt;a rel=&quot;license&quot; href=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; target=_blank&gt;크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스&lt;/a&gt;에 따라 이용하실 수 있습니다.
			&lt;!-- Creative Commons License--&gt;
			&lt;!-- &lt;rdf:RDF xmlns=&quot;http://web.resource.org/cc/&quot; xmlns:dc=&quot;http://purl.org/dc/elements/1.1/&quot; xmlns:rdf=&quot;http://www.w3.org/1999/02/22-rdf-syntax-ns#&quot;&gt;
			&lt;Work rdf:about=&quot;&quot;&gt;
			&lt;license rdf:resource=&quot;http://creativecommons.org/licenses/by-nc-nd/2.0/kr/&quot; /&gt;
			&lt;/Work&gt;
			&lt;License rdf:about=&quot;http://creativecommons.org/licenses/by-nc-nd/&quot;&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Reproduction&quot;/&gt;
			&lt;permits rdf:resource=&quot;http://web.resource.org/cc/Distribution&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Notice&quot;/&gt;
			&lt;requires rdf:resource=&quot;http://web.resource.org/cc/Attribution&quot;/&gt;&lt;prohibits rdf:resource=&quot;http://web.resource.org/cc/CommercialUse&quot;/&gt;&lt;/License&gt;&lt;/rdf:RDF&gt; --&gt;&lt;/div&gt;&lt;/fieldset&gt;&lt;div id=&quot;variety_topic&quot; class=&quot;widget&quot;&gt;
	&lt;h3&gt;다양한 이야깃거리&lt;/h3&gt;&lt;div id=&quot;category_related&quot; class=&quot;widget&quot;&gt;
		&lt;h4&gt;카테고리 관련글&lt;/h4&gt;
		&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/642&quot; title=&quot;내장 비트맵 폰트를 활성화 시키는 방법&quot;&gt;내장 비트맵 폰트를 활성화 시키는 방법&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 13:11:08&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/641&quot; title=&quot;케이스 스터디: 솔라리스10에서 DTrace 와 truss 사용하기&quot;&gt;케이스 스터디: 솔라리스10에서 DTrace 와...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/21&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/639&quot; title=&quot;플래시 어카이브로 부터 솔라리스10 Branded 존 설치하기&quot;&gt;플래시 어카이브로 부터 솔라리스10 Branded...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/21&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/631&quot; title=&quot;DTrace 를 이용하여 Defunct 프로세스 문제 해결하기&quot;&gt;DTrace 를 이용하여 Defunct 프로세스...&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/08/01&lt;/span&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sdnkorea.com/blog/630&quot; title=&quot;솔라리스10 08/07 에서 존 리소스 컨트롤&quot;&gt;솔라리스10 08/07 에서 존 리소스 컨트롤&lt;/a&gt; &lt;span class=&quot;modified&quot;&gt;- 2008/07/29&lt;/span&gt; &lt;/li&gt;
&lt;/ul&gt;
		&lt;/div&gt;&lt;/div&gt;</description>
			<category>관리자코너</category>
			<category>Branded Zone</category>
			<category>branded zone 생성</category>
			<category>Branded Zones</category>
			<category>branded 존 생성</category>
			<category>Flash Archive</category>
			<category>Native zone</category>
			<category>solaris</category>
			<category>solaris 10</category>
			<category>네이티브 존</category>
			<category>솔라리스10 brand</category>
			<category>의존성 트리</category>
			<author>(SDNKorea)</author>
			<guid>http://sdnkorea.com/blog/639</guid>
			<comments>http://sdnkorea.com/blog/639#entry639comment</comments>
			<pubDate>Tue, 19 Aug 2008 19:25:49 +0900</pubDate>
		</item>
		<item>
			<title>자바 웹 스타트 애플리케이션을 CD-ROM으로 배포</title>
			<link>http://sdnkorea.com/blog/638</link>
			<description>&lt;A href=&quot;http://java.sun.com/products/javawebstart/&quot;&gt;자바 웹 스타트&lt;/A&gt;(JWS)는 웹 기반으로 애플리케이션을 배포할 수 있지 않습니까? 그런데 사람들은 왜 CD-ROM으로 자바 웹 스타트(JWS) 애플리케이션을 배포하려고 할까요? 이유는 여러 가지입니다. 우선, 대규모 애플리케이션이라면 고속 광대역 회선으로도 설치 프로그램 전체를 다운로드하기가 만만치 않을 수 있습니다. 둘째로, 기업 보안 등의 이유로 인해 온라인 연결이 안 되는 데스크탑도 많고 또 인터넷에 액세스할 수 없는 시스템도 많습니다. 마지막으로, 그저 CD가 더 좋다는 사람들이 많기 때문입니다. 
&lt;P&gt;클라이언트 기업에서 광대역 회선이 거의 없는 지역을 비롯하여 전 세계에 자사의 애플리케이션을 배포해 달라고 요청합니다. 이 애플리케이션에는 수많은 제품에 대한 정보와 함께 상세한 도면과 다이어그램까지 들어 있습니다. 애플리케이션의 상당 부분은 이러한 정보로 구성되어 있으며 JVM을 포함한 전체 설치 용량은 40MB를 넘어섭니다. 또 이 회사에서는 무역 박람회 등에서도 홍보물과 함께 이 애플리케이션을 CD에 담아 배포하고 싶다고 합니다. 그러므로 CD 배포도 준비해야 합니다. 보통, CD 설치에는 여러 가지 상업적 설치 프로그램이나 오픈소스 설치 프로그램을 이용하게 됩니다. 그러나 자바 웹 스타트로 실행하게 되어 있는 애플리케이션은 보통의 설치 프로그램에서와 달리 특정 위치에 설치해야 하며 사용자가 재량을 발휘할 여지가 없습니다.&lt;/P&gt;
&lt;P&gt;이 기사에서는 CD와 인터넷 양쪽 모두를 이용하는 애플리케이션 설치 단계에 대해 설명합니다. 설치 프로세스에 필요한 조건은 다음과 같습니다.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;설치된 애플리케이션은 업데이트를 스스로 확인하고 JWS 캐시와 통합되어야 합니다. 
&lt;LI&gt;기존 또는 최신 버전의 자바 없이도 설치 후 즉시 시스템에서 실행할 수 있어야 합니다. 
&lt;LI&gt;설치된 애플리케이션에는 인터넷 연결이 필요 없습니다. 
&lt;LI&gt;설치된 프로그램은 사용하기 쉬워야 하며 사용자 인터페이스는 간단해야 합니다. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;애플리케이션 설치는 보통 일반적인 설치 프로그램을 사용하여 이루어집니다. 그러나 기존의 설치 프로세스에서는 효율성 제고를 위해 JWS를 인식하지 못하는 별도의 애플리케이션을 작성하는 경우가 많았습니다. 따라서 업데이트가 발표될 때마다 사용자는 새 버전을 다운로드하여 설치해야 했습니다. 이와 달리 JWS 애플리케이션은 업데이트된 구성요소만 다운로드하므로 프로세스의 효율성과 신뢰성이 훨씬 더 높습니다. 그러므로 이 기사에서는 JWS 애플리케이션 설치 프로그램에 대해서도 설명하고자 합니다.&lt;/P&gt;
&lt;H3 id=jws-primer&gt;&lt;FONT size=3&gt;&lt;br /&gt;JWS 프라이머&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;자바 웹 스타트가 있으면 &lt;A href=&quot;http://java.sun.com/products/javawebstart/download-spec.html&quot;&gt;JNLP&lt;/A&gt; 파일 링크를 통해 자바 애플리케이션을 시작할 수 있습니다. 이 JNLP 파일은 애플리케이션에 대한 진입점 또는 기본 메소드를 설명하는 한편 애플리케이션에서 사용할 리소스를 참조합니다.&lt;/P&gt;
&lt;P&gt;JWS 애플리케이션을 시작하면 JVM이 필요한 리소스에 액세스하려고 시도하면서, 경우에 따라 리소스를 업데이트하고 파일을 캐시로 복사합니다. 그 뒤로 이 애플리케이션을 시작하면 JWS가 이 캐시부터 확인하므로 리소스 다운로드 단계를 건너뛸 수 있습니다. 클라이언트 시스템이 오프라인 상태이거나 서버에 연결할 수 없는 경우, JWS는 오프라인 모드로 애플리케이션을 실행합니다.&lt;/P&gt;
&lt;P&gt;JWS 시작 파일(JNLP 파일)이 CD에 들어 있는 경우, JWS는 서버에 연결하여 새 파일을 다운로드하려고 시도합니다. 물론 클라이언트 시스템이 온라인 상태일 때 이렇게 하는 것은 CD를 이용한 파일 배포의 취지에 어긋나는 일입니다. 대신에 우리는 앞서 JWS가 애플리케이션을 로드한 것처럼 JWS 캐시를 업데이트할 방법을 찾아야 합니다.&lt;/P&gt;
&lt;H3 id=updating-the-jws-cache&gt;&lt;FONT size=3&gt;&lt;br /&gt;JWS 캐시 업데이트&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;자바 5 버전의 JWS에는 잘 알려진 &lt;CODE&gt;-import&lt;/CODE&gt; 옵션이 있습니다. 이것은 특정 위치의 JWS 애플리케이션을 캐시로 가져오는 옵션입니다.&lt;/P&gt;
&lt;P&gt;이 위치에 있는 CD 이미지는 보통 웹 서버에 배치되는 것, 즉 JNLP 파일과 이 JNLP 파일에서 참조하는 리소스 및 .jar 파일 등의 사본에 불과합니다. 서블릿을 사용하여 JNLP를 서비스하는 경우, CD 이미지를 실행하려면 생성된 JNLP 파일의 완벽한 스냅샷이 필요합니다.&lt;/P&gt;
&lt;P&gt;따라서 다음을 호출하여 JWS 캐시에 CD 이미지를 설치할 수 있습니다.&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;&amp;lt;JAVA_HOME&amp;gt;/jre/bin/javaws -codebase &amp;lt;CACHE_IMAGE&amp;gt; -import &amp;lt;CACHE_IMAGE&amp;gt;/&amp;lt;XXXX&amp;gt;.jnlp&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;여기서 &lt;CODE&gt;&amp;lt;JAVA_HOME&amp;gt;&lt;/CODE&gt;은 새 JVM 또는 기존 JVM의 루트이고, &lt;CODE&gt;&amp;lt;CACHE_IMAGE&amp;gt;&lt;/CODE&gt;은 CD에서 JWS 애플리케이션의 위치이며, &lt;CODE&gt;&amp;lt;XXXX&amp;gt;&lt;/CODE&gt;는 애플리케이션 JNLP 파일의 이름입니다. 이 명령을 자동화하고 간단한 GUI로 래핑하는 방법은 나중에 설명하겠습니다.&lt;/P&gt;
&lt;P&gt;캐시에 저장된 애플리케이션을 설치하는 동안 JWS는 애플리케이션 시작을 위한 단축키를 바탕 화면이나 메뉴에 설치할지 묻는 메시지를 표시합니다. JWS 설치가 완료된 후 JWS를 다시 호출하여 새로 설치한 애플리케이션을 시작할 수 있습니다.&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;&amp;lt;JAVA_HOME&amp;gt;/jre/bin/javaws -import &amp;lt;CACHE_IMAGE&amp;gt;/&amp;lt;XXXX&amp;gt;.jnlp&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;여기서 다시 한 번 CD를 사용합니다. 그러나 이번에는 JWS가 JNLP 파일에서 참조하는 설치 리소스를 사용하게 됩니다. 시스템이 인터넷에 연결되어 있을 때는 통상적인 방법으로 업데이트를 확인한 다음, 애플리케이션을 시작합니다. 네트워크 연결이 설정되지 않았다면 CD에 저장된 상태 그대로 애플리케이션이 시작됩니다.&lt;/P&gt;
&lt;P&gt;다음 번에 이 애플리케이션을 시작하는 사용자는 메뉴 또는 바탕 화면의 단축키를 사용할 수 있으며 CD는 이제 필요 없습니다. 아니면 웹 페이지의 링크를 사용하여 애플리케이션을 시작할 수 있습니다. 이 링크는 동일한 URL/JNLP 파일 조합, 예를 들면 해당 웹 사이트에 있던 원래 버전을 가리키는 링크여야 합니다.&lt;/P&gt;
&lt;H3 id=jvm-complications&gt;&lt;FONT size=3&gt;&lt;br /&gt;JVM 문제&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;지금까지 설명한 내용에는 허점이 하나 있습니다. 위의 명령을 실행하려면 JVM이 있어야 하는데, 드물기는 하지만 JVM이 설치되어 있지 않거나 시스템 경로에 기본값으로 설정되어 있지 않아서 별도의 조치를 통해 사용 가능한 JVM을 찾아야 하는 경우가 있습니다. 이와 함께 사용자가 CD를 넣으면 설치가 시작되고 그 과정에서 기존 JVM이 있는지 자동으로 확인해야 합니다. 따라서 JVM 확인 프로세스는 다음과 같이 이루어집니다.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;설치 프로그램이 JVM을 확인합니다. 
&lt;LI&gt;없으면 JVM을 설치합니다. 
&lt;LI&gt;설치 프로그램이 시작되고 사용자 라이센스 정보가 표시됩니다. 
&lt;LI&gt;대상 JVM(위 1과 다른 버전을 애플리케이션이 요구하는 경우, 해당 버전)을 설치합니다. 
&lt;LI&gt;JWS 캐시를 가져옵니다. 
&lt;LI&gt;JWS 애플리케이션을 시작합니다. &lt;/LI&gt;&lt;/OL&gt;
&lt;P&gt;JWS &lt;CODE&gt;-import&lt;/CODE&gt; 옵션을 사용하기 위한 최소 JVM 버전이 자바 5라는 사실 때문에 몇 가지 문제가 더 발생합니다. 다시 말해, JVM이 설치되어 있고 애플리케이션에 사용할 수 있는 상태이더라도 이 import 옵션을 지정하려면 그 이상의 최신 JVM이 필요하게 됩니다. 둘째, 가져오기 프로세스에는 시간이 약간 걸리는데 애플리케이션을 시작하려면 먼저 이 프로세스를 마쳐야 합니다. 이렇게 실행이 지연되면 일반적인 다른 설치 프로그램과 같은 성능을 얻기가 어려워집니다.&lt;/P&gt;
&lt;P&gt;이러한 문제를 고려한 결과, 위의 단계를 자동으로 수행할 수 있는 맞춤 시작형 애플리케이션을 제작하기로 했습니다.&lt;/P&gt;
&lt;H3 id=running-the-installation&gt;&lt;FONT size=3&gt;&lt;br /&gt;설치 프로그램 실행&lt;/FONT&gt;&lt;/H3&gt;
&lt;P&gt;설치 프로세스의 실제 과정은 대부분 JWS &lt;CODE&gt;-import&lt;/CODE&gt; 명령으로 처리되므로, 이 시작 애플리케이션의 주된 임무는 적절한 명령으로 JVM을 찾아 시작한 뒤 사용자에게 작업의 진행 과정을 GUI로 알려주는 것입니다.&lt;/P&gt;
&lt;H5 id=finding-the-jvm&gt;&lt;br /&gt;JVM 찾기&lt;/H5&gt;
&lt;P&gt;Windows에서는 시스템 레지스트리의 &lt;CODE&gt;HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Runtime Environment&lt;/CODE&gt; 키 아래에서 JVM을 찾을 수 있습니다. 이 키는 값이 여러 개일 수 있으며, 따라서 시작 애플리케이션은 레지스트리 항목을 반복하여 점검하면서 사용 가능한 최신 버전의 JVM을 찾아냅니다.&lt;/P&gt;
&lt;P&gt;다음 메소드는 최소 및 최대 버전 번호의 인수를 대입하여 JVM 경로를 찾으려고 시도합니다.&lt;/P&gt;&lt;PRE&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;
private String getInstalledPath( 
  int majorMin, int minorMin, int revMin,
  int majorMax, int minorMax, int revMax )
  {
    String installedPath = null;
    int latestVersion = 0;

    String keyRoot = 
         &quot;HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft&quot; + 
         &quot;\\Java Runtime Environment&quot;;
    Vector results = getRegEntries( &quot;\&quot;&quot; + keyRoot + &quot;\&quot; /s&quot; );
    int numEntries = results.size();
    for ( int i = 0; i &amp;lt; numEntries; i++ ) {
    String key = results.get( i++ ).toString();
    int pos = key.indexOf( &quot;Java Runtime Environment&quot; );
    if ( pos &amp;gt; 0 ) {
      pos += &quot;Java Runtime Environment&quot;.length() + 1;
      String version = key.substring( pos );
      String parts[] = version.split( &quot;[._]&quot; );
      int majorVersion, minorVersion, revision;
      majorVersion = Integer.parseInt( parts[ 1 ] ); 
      if ( parts.length &amp;gt; 3 )
        minorVersion = Integer.parseInt( parts[ 2 ] );
      else
        minorVersion = 0;
     
      if ( parts.length &amp;gt; 4 )
        revision = Integer.parseInt( parts[ 3 ] );
      else
        revision = 0;
        
      if ((( majorVersion == -1 ) || 
           ( majorVersion &amp;gt;= majorMin )) &amp;amp;&amp;amp;

          (( majorVersion == -1 ) || 
           ( majorVersion &amp;lt;= majorMax ))) {
        if ((( minorMin == -1 ) || 
             ( minorVersion &amp;gt;= minorMin )) &amp;amp;&amp;amp; 
            (( minorMax == -1 ) || 
             ( minorVersion &amp;lt;= minorMax ))) {
          if ((( revMin == -1 ) || 
               ( revision &amp;gt;= revMin )) &amp;amp;&amp;amp; 
              (( revMax == -1 ) || 
               ( revision &amp;lt;= revMax ))) {
            // Prefer the neweset acceptable version
            int thisVersion = majorVersion * 10000 + 
                minorVersion * 100 + revision;
            if ( thisVersion &amp;gt; latestVersion ) {
              String value = null;
              while ( i &amp;lt; numEntries ) {
                value = results.get( i++ ).toString().trim();
                if ( value.startsWith( &quot;JavaHome&quot; )) 
                  break;
              }
              
              installedPath = value.substring( 
                value.indexOf( &quot;REG_SZ&quot; ) +  6 ).trim();
              latestVersion = thisVersion;
            }
          }
        }
      }
    }
  }

  return installedPath;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/PRE&gt;
&lt;P&gt;위 메소드의 키는 레지스트리 항목을 찾기 위한 키입니다. 레지스트리 값을 찾아주는 API는 여러 가지 있지만, 이 상황에서 가장 실용적인 것은 간단한 명령행 &lt;CODE&gt;REG QUERY &amp;lt;key&amp;gt;&lt;/CODE&gt;입니다. 여기서 &lt;CODE&gt;&amp;lt;key&amp;gt;&lt;/CODE&gt;는 쿼리할 레지스트리 경로입니다. 다음 메소드는 명령을 실행한 다음, 출력된 스트림 항목을 읽어 이를 &lt;CODE&gt;Vector&lt;/CODE&gt;로 반환합니다.&lt;/P&gt;&lt;PRE&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;
private Vector getRegEntries( String key )
{
  Vector results = new Vector();

  try {
    Process proc = Runtime.getRuntime().exec( &quot;REG QUERY &quot; + 
      key );
    InputStream is = proc.getInputStream();
    InputStreamReader isr = new InputStreamReader(is);


    BufferedReader br = new BufferedReader(isr);
    String result = &quot;&quot;;
    String line; 

    while (( line = br.readLine()) != null ) {
      line = line.trim();
      results.add( line );
    } 

    return results;
  }
  catch ( Exception ex ) {
    message( language.getString(&quot;6&quot;) + ex.getMessage() );
    ex.printStackTrace();
  }

  return null;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/PRE&gt;
&lt;H5 id=install-the-jvm&gt;&lt;br /&gt;JVM 설치&lt;/H5&gt;
&lt;P&gt;적당한 JVM을 찾을 수 없으면 CD에서 설치하면 됩니다. 단, 그 위치를 알고 있어야 합니다. 시작 프로그램은 properties 파일을 사용하여 필요한 여러 가지 리소스를 파악한 다음, 이 메커니즘을 통해 JVM 설치 패키지로 보낼 수 있습니다. 여기서도 마찬가지로, JVM 설치를 시작하려면 올바른 명령을 실행할 수 있어야 합니다. 그러나 이번에는 프로세스의 실행 시간이 비교적 길기 때문에 완료될 때까지 조금 기다려야 합니다. 실행(&lt;CODE&gt;exec&lt;/CODE&gt;)된 프로세스의 &lt;CODE&gt;waitFor&lt;/CODE&gt; 메소드는 완료될 때까지 스레드를 대기시키는 한편 UI 스레드의 차단을 방지하기 위해 이를 &lt;CODE&gt;SwingWorker&lt;/CODE&gt; 안에 중첩시킵니다.&lt;/P&gt;&lt;PRE&gt;&lt;pre class=&quot;prettyprint&quot;&gt;&lt;code&gt;
private void installJre()
{
  try {
    final String javaInstall = (String)props.get( 
        &quot;jre_installer&quot; );
    status.setText( language.getString(&quot;3&quot;) );

    SwingWorker worker = new SwingWorker() 
    {
      public Object construct() 
      {
        try {
          Process process = Runtime.getRuntime().