'프로그래밍/System program'에 해당되는 글 3건

  1. 2013.04.22 멀티스레드에 관하여 2
  2. 2013.04.22 멀티스레드에 관한 글
  3. 2013.04.21 mmap
프로그래밍/System program 2013. 4. 22. 10:58


1. 동기화 개체에 대한 잘못된 생각들

  스레드를 동기화한다 함은 스레드 간의 실행순서를 정하거나, 스레드 간 특정작업이 동시에 일어나지 않도록 구현하는 것을 말합니다. 

1) Manager Thread가 Worker Thread를 생성한 후, Worker Thread의 초기화가 끝날 때까지 기다려야 하는 경우. 이런 경우에는 보통 Event 개체나 메시지를 사용합니다.

2) 전역 데이터에 접근할 때에 한번에 스레드 한개씩만 해당 데이터를 사용하도록 구현하는 경우 : 이 경우에는 보통 CriticalSection 을 사용합니다. 일반적으로 스레드 동기화라 함은 이러한 경우를 말합니다.

3) 일정 숫자 이상의 스레드(혹은 프로세스)가 동시에 특정 자원을 사용하거나 동작하지 못하도록 하는 경우 : 이 경우에는 보통 Semaphore를 사용합니다.


CriticalSection을 사용하는 데에 있어서 초보자분들은 다음과 같은 착각을 하기 쉽습니다.

착각1) EnterCriticalSection()을 호출하면 Data에 Lock이 걸리고 다른 Thread가 접근하지 못하게 된다. (X)

==> CriticalSection 등의 동기화 개체에 Lock을 건다 함은 화장실이라는 Resource에 문을 걸어 잠그는 개념이 아니라, 화장실의 문에 "사용중"이라고 써붙이는 개념입니다. 이게 무슨 얘기냐 하면, "g_szData 라는 Data에 접근할 때는 crit_szData에 Lock을 걸어야 한다"라고 개발자가 스스로 규칙을 세우고, 코드의 모든 부분에서 g_szData를 사용할 때 CriticalSection에 Lock을 걸도록 구현해야 한다는 뜻입니다. 화장실의 문에 "사용중"이라고 써붙이고 들어갔는데, 어떤 사람이 문에 붙어있는 표시를 확인하지 않고 문을 열고 들어간다면? 운이 좋으면 문제가 안생기겠지만 재수가 없으면 민망한 상황이 벌어질 것입니다. 

엄밀히 말하면 데이터에 동기화개체는 스레드 들이 특정 데이터에 동시 Read/Write하지 못하도록 하는 기능을 제공하지 않습니다. 단지 동기화개체에 동시에 Lock을 걸지 못하는 기능을 제공할 뿐이죠. :)


착각2) 데이터에 Read할 때는 동기화가 필요 없다. 따라서 EnterCriticalSection은 Data에 Write를 수행할 때만 수행하면 된다. (X)

==> Data를 Read하는 스레드에서는 그냥 Read를 하면서 Data에 Write를 하는 스레드에서만 Lock을 건다고 해서 다른 스레드가 그 Data에 접근을 못하게 되는 것이 아닙니다. 어떤 CriticalSection에 Lock을 건다고 해서 스레드간 ContextSwitching이 중지되는 건 더더욱 아닙니다. 보호하고자 하는 데이터를 참조하는 모든 부분에 동기화 처리를 해주지 않으면 동기화 개체를 사용하는 것은 아무런 의미도 없습니다. 
간단하게 생각하면 CriticalSection이란 보호할 데이터를 사용하는 중에 BOOL형 변수에 "사용중"이라는 의미로 "TRUE" 값을 Setting하는 이상의 의미는 없습니다. 단지 두 Thread에서 동시에 TRUE를 설정하지 못하도록 OS에서 보장해준다는 점과 TRUE를 Setting하려고 할 때 이미 TRUE라는 값이 Setting되어 있다면 이 변수가 FALSE로 바뀔 때까지 스레드가 BLOCK되는 등의 처리가 자동으로 구현되어 있다는 정도가 차이가 있을 뿐입니다.
단지 프로그램 전체에 걸쳐서 어떠한 "Write"도 수행되지 않고 "Read"만 수행되는 데이터라면 동기화가 필요 없습니다. 

대부분의 개발자 분들은 이런 얘길 보면서 "이렇게 당연한  얘기를 왜 하나?"라고 생각하시겠지만... 바로 얼마 전에 십 수년간 개발을 하신 서버 개발자께서 "CriticalSection에 Lock을 걸면 말이쥐... 다른 스레드들은 이 데이터에 접근을 못하게 되는 거란다"라고 친절하게 설명해주시는 걸 듣고... 까무라치는 줄 알았습니다. ㅡ.ㅡ

※ 선언 함수나 초기화 함수를 보면 알수 있듯이, CriticalSection은 그 자체로서 어떠한 데이터와도 연관되지 않습니다. 어떠한 데이터를 보호하는데 어떤 CriticalSection 개체를 사용하겠다 하는 것은 순전히 개발자의 로직상으로 구현되는 부분입니다. 위에서 얘기했듯이 OS에서는 동시에 한개의 스레드만 EnterCriticalSection에 성공할 수 있다는 것 외에는 아무것도 보장하지 않습니다. 나머지는 개발자의 몫인 거죠.


2. Case I : Multiple-Reader + Multiple-Writer 환경 (CriticalSection Per Data Model)

  멀티스레드 환경에서 발생할 수 있는 가장 일반적인 경우는 다수의 스레드가 동시에 데이터를 읽고 쓰는 경우입니다. 이 경우에는 어떠한 "읽기"와 "읽기", "읽기"와 "쓰기" 혹은 "쓰기"와 "쓰기" 도 동시에 발생해서는 안되며, 완전하게 동시접속이 차단되어야 합니다. 이렇게 처리하는 것을 직렬화(Serialize)한다고 합니다.

  이런 환경을 구현하기 위해서는 CriticalSection을 접속하고자 하는 Data의 수만큼 만들고, (읽기/쓰기에 상관없이) Data에 접근할 때마다 해당 Data에 Matching 되는 CriticalSection에 대해 EnterCriticalSection을 수행해주어야 합니다. 말하자면 "CriticalSection Per Data" 정도 되겠네요.

가장 안전한 환경이 구현되지만, 병렬수행이 불가능해지므로 성능은 최악이 됩니다. 

그림으로 표현하면 다음과 같이 되겠네요.



3. Case II : Multiple-Reader + Single-Writer 환경 (CriticalSection Per Thread Model)

  모든 스레드가 읽기와 쓰기를 행한다면 Case I  과 같이 직렬화를 시켜야겠지만, 대부분의 Server용 Application에서는 다수의 Worker Thread는 전역 데이터에 대해 Read만을 수행하고 한개의 Manager Thread가 Write를 수행하는 구조인 경우가 많습니다. 대표적인 예가 Manager Thread가 기록한 정책을 참조하여 Worker Thread가 클라이언트의 접속을 처리하는 경우를 예로 들 수 있겠죠. (Thread Pool 이 보통 이런 동작을 합니다.)

이러한 경우는 다음과 같은 특징이 있습니다.


1) Read의 빈도가 매우 높고, Write의 빈도는 낮다. 

2) Read와 Read는 동시에 이루어지는 것이 바람직하지만 Write와 Read는 동시에 이루어져선 안된다.

3) WokerThread간의 병렬처리가 이루어져야 하므로 Read의 속도가 매우 중요하며 Write의 성능은 상대로 덜 중요하다.


위의 조건을 만족시키기 위해서는 스레드와 동기화 개체들을 어떤 식으로 구성해야 할까요? 제가 내린 결론은 다음과 같습니다. (더 좋은 방법을 아시는 분은 가르쳐주세요. ^^)

1) WorkerThread 마다 CriticalSection을 하나씩 생성한다. WorkerThread는 각자 자기의 CriticalSection을 가지고 있다. 말하자면 워커스레드가 6개라면 CriticalSection도 6개가 생성되며 이것이 Array처럼 접근되도록 구현된다.

2) WorkerThread 는 작업을 시작할 때마다 자기의 CriticalSection에 대해 EnterCriticalSection()을 호출하고 작업을 끝낸 후에는 LeaveCriticalSection을 호출합니다. 이렇게 되면 각 WorkerThread 간에는 작업이 병렬수행되며, 전역 Data에 대해서도 병렬 Read가 이루어집니다. (이때 ManagerThread 는 쉬고 있겠죠)

3) ManagerThread 가 정책을 업데이트해야 할 때는 For Loop 를 돌면서 모든 CriticalSection에 대해 EnterCriticalSection()을 호출합니다. 일단 ManagerThread가 CriticalSection에 Lock을 걸고 나면 해당 WorkerThread는 새로운 작업을 시작하지 못하기 때문에, For Loop가 끝나게 되면 결과적으로 ManagerThread는 모든 WorkerThread를 정지시키게 됩니다. (이때는 물론 시간이 좀 걸리겠죠? ^^)

4) ManagerThread는 정책을 수정합니다.

5) ManagerThread는 For Loop를 돌면서 모든 CriticalSection에 대해 LeaveCriticalSection()을 호출합니다. 이제 WorkerThread들은 다시 자신의 CriticalSection을 획득하고 밀린 일을 처리할 수 있습니다.


그림으로 표현하면 대략 다음과 같이 되겠네요.


WorkerThread간의 읽기작업을 표현하면 다음과 같습니다.


ManagerThread가 쓰기 작업을 진행할 때는 다음과 같이 됩니다.


말하자면... Write속도를 희생시켜서 Read속도를 증가시킨다고나 할까요? ^^


4. Case III : 동기화를 하지 않는 방법(?)

  "멀티스레드 프로그래밍에 관한 고찰 (1)" 에서 논했듯이 멀티스레드가 Data에 동시접근한다고 해도 경우에 따라서는 동기화 하지 않고 사용할 수 있습니다. 만약 이게 가능하다면 멀티스레드 프로그램은 최고의 효율을 얻을 수 있습니다. 이렇게 구성하기에 앞서 해당 Case가 이런 방식으로 구성 가능한지 검토해야 하며, 가능하다면 자료구조가 안전한 동시접근이 가능하도록 설계되어야 합니다.

정수형 Data가 Linked List에 저장되는 경우의 예를 들어 보겠습니다.

1) Data가 변경될 때 Linked List에 Entry가 추가/삭제되는 경우에는 반드시 스레드 동기화가 필요합니다. 반대로 시종일관 LinkedList 자체는 변화가 없이 각 Entry의 정수형 데이터값만 변경시키는 경우에는 동기화 없이도 Concurrent Read/Write가 안전하게 수행될 수 있습니다. 
   이러한 경우의 예를 들면 오목게임의 바둑판을 들 수 있습니다. 모든 좌표에 대해 게임을 시작하기 전에 19 X 19 개의 좌표 Data를 생성한 후, 게임이 진행되는 동안에는 해당 좌표에 대한 Data(흑/백/無)만 Update될 뿐 새로운 좌표가 추가되지는 않습니다. 이런 경우라면 동기화가 필요하지 않습니다.

2) 만약 Data가 Linked List에 추가/삭제되어야 하는 경우라면, 추가되는 데이터의 "경우의 수"에 대해 생각해보아야 합니다. 경우에 따라서는 Insert될 수 있는 Data의 경우의 수가 한정되어 있어 초기화시에 모든 경우의 수에 대한 메모리를 미리 생성해놓고 시작할 수 있는 경우가 있습니다. 이러한 경우라면 동기화 없이 멀티스레드가 동작할 수 있습니다.
   예를 들어, 사내 IP체계를 B Class를 사용하는 회사에서 IP를 사용하는 Mac주소와 사용자 정보를 저장하는 자료구조가 있다고 가정해보겠습니다. 

. 새로운 IP가 생성될 때마다 Linked List에 Entry가 생성되는 방식으로 설계한다면 스레드 동기화가 필요하며, 동기화하지 않을 경우 Entry를 LinkedList에 Insert하는 순간 Access Violation이 발생할 수 있습니다.

. 모든 경우의 수 (255 * 255 = 65525개)만큼의 Entry를 처음에 일괄 생성해놓고, 사용하지 않는 IP 에 대해서는 FALSE, 사용하는 IP에 대해선 TRUE를 기록하여 미사용 IP를 관리하고, 사용중인 IP에 대해서는 Mac주소와 사용자정보를 미리 할당된 메모리에 memcpy하는 방식으로 자료구조를 설계할 경우 동기화 처리 없이도 안전하게 Concurrent Read/Write가 가능합니다. 한마디로 "메모리를 희생하여 속도를 향상"시키는 방법이죠 :)




출처 : http://kuaaan.tistory.com/116

'프로그래밍 > System program' 카테고리의 다른 글

멀티스레드에 관한 글  (0) 2013.04.22
mmap  (0) 2013.04.21
//
프로그래밍/System program 2013. 4. 22. 10:57

  예전에는 고사양이라 하면 힘쎈 CPU를 의미했지만 지금 시대의 고사양이란 CPU 여러 개를 의미합니다. 이른바 멀티코어의 시대죠. 예전에 3.4GHz 4CPU가 최고사양 서버였다고 하면 요즘에는 1.6GHz 16Core (4Core * 4ea)가 동급으로 받아들여집니다. 

 이러한 H/W적인 패러다임의 변화는 S/W 개발에도 영향을 주어 예전에는 (어셈블리) 코드 한줄이라도 줄이는 게 퍼포먼스 향상의 열쇠였다고 한다면 지금은 여러 스레드(Thread) 들이 한 머쉰에서 서로 엉키지 않고(!) 조화롭게 돌아가는 구조를 구현하는 것이 퍼포먼스 향상의 열쇠라고 볼 수 있습니다. 

 그렇다면 멀티스레드 프로그램의 성능을 결정하는 열쇠는 무엇일까요?

 먼저 "스레드의 수"를 생각해 볼 수 있습니다.
 멀티스레드 프로그래밍을 해보시지 않으신 분들은 일단 스레드를 많이 만들면 퍼포먼스도 올라갈 것이라고 생각하시는 경향이 있읍니다만 이것은 잘못된 생각입니다. 
 중요한 것은 한개의 CPU는 동시에 한 개 씩의 스레드만 실행시킬 수 있다는 사실입니다. 스레드가 여러개가 생성되면 CPU는 각각의 스레드를 시분할하여 각각의 스레드를 번갈아가며 실행하게 되는데, 이때 이전 스레드의 문맥 정보 (레지스터 값, 실행중인 스택 정보 등)을 백업받고 백업받아놓았던 다음 스레드의 문맥정보를 로딩하는 과정을 거치게 됩니다. 이 과정을 Context Switching(문맥 교환이라고 번역하더군요) 이라고 하는데, 이러한 스레드가 많아질 수록 Context Switching 에 많은 부하가 걸리기 때문에 오히려 퍼포먼스는 떨어지게 됩니다. 
 그렇다면 스레드가 적을수록 퍼포먼스가 좋아질까요? 물론 그렇지는 않습니다. ^^
 

 위 그림과 같이 스레드는 작업을 진행함에 따라 Running <-> Waiting , Sleeping, Blocked 등으로 상태변화를 하게 되는데, 멀티스레드 프로그램은 한 스레드가 Waiting, Sleeping, Blocked 중일 때 CPU가 다른 스레드를 실행시킬 수 있기 때문에 동시성(Concurrency)이 높아져서 성능이 좋아지는 것입니다. 바꾸어 말하면 I/O가 많이 발생하는 프로그램일 수록 멀티스레딩의 효과를 크게 볼 수 있다고 말할 수도 있습니다.

위의 두가지 면을 종합할 때 멀티스레드 프로그램의 성능은 스레드의 "동시성 향상 효과"와 "Context Switching 비용"의 Trade Off 에 의해 결정된다고 말할 수 있습니다.
 따라서 가장 적절한 스레드의 수는 CPU의 수와 스레드가 수행하는 작업의 성격을 함께 고려하여 결정되는데 일반적으로는 연산 위주의 작업의 경우 CPU당 2~3개, I/O 위주 작업의 경우 CPU당 5개 내외를 적절한 스레드의 수로 가이드하며, 보통 스레드 풀(Thread Pool)을 생성할 때 워커 스레드 (Worker Thread)의 수를 산정하는 방식으로 사용됩니다.

 요즘 네트워크 프로그램에서 많이 사용되는 IOCP (Input Output Completion Port)가 성능이 좋은 이유는 I/O가 진행되는 동안 스레드가 스위칭되거나 블러킹되지 않기 때문에 스레드의 Context Switching을 최소화할 수 있고, 따라서 필요한 스레드의 수를 최소화할 수 있기 때문입니다. 그런 면에서 어찌보면 최소한의 스레드를 써야 높은 성능을 낼 수 있다고 볼 수 있는 거죠.


   그렇다면 "동시성 향상 효과"를 높이는 요인은 무엇이 있을까요? 바로 "효율적인 스레드 동기화" 를 들 수 있습니다.
  멀티스레드 프로그래밍은 프로세스의 동시성을 향상시켜 성능을 향상시키는 효과가 있지만, 여러 스레드 들이 동시에 데이터를 접근하면서 생기는 문제들이 빛과 그림자처럼 쫓아다니게 됩니다. 예를 들어 스레드 A가 링크드 리스트에서 Read를 시도하려고 하는 순간에 스레드 B가 해당 링크드 리스트에 ClearAll() 을 수행한다면 어떤일이 벌어질까요? 스레드 A는 메모리 폴트를 발생시키고 해당 프로세스는 중지되고 말 것입니다. 이러한 일을 방지하기 위해서는 스레드들이 링크드 리스트에 동시에 접근하지 못하도록 직렬화(Serialize)시킬 필요가 있는데 이런 작업을 "스레드 동기화"라고 합니다. 
  스레드 동기화가 잘못되었을 때 생기는 문제들이나 동기화 개체 사용법 등에 대해서는 인터넷에 좋은 포스트가 많이 공개되어 있으니, 여기서는 어떻게 하면 보다 효율적인 스레드 동기화를 구현할 수 있을 것인가에 대해 생각해보겠습니다. 
 문제는 스레드 동기화의 정도가 높아질수록 데이터에 대한 단일접근이 보장되어 안정성과 데이터 무결성은 높아지지만, 반면에 데이터에 접근할 때의 동시성이 저하되어 성능은 (형편없이) 떨어지게 됩니다. 여기서도 Trade Off 문제가 발생하는 거죠. 원칙적으로 모든 전역 데이터(Global Data)에 접근할 때 CriticalSection등의 동기화 개체를 사용하여 동시접속을 차단하는 것이 원칙이겠지만 그렇게 하게 되면 너무 성능이 떨어지기 때문에, 대부분의 서버 개발자들은 "이정도는 괜찮더라"는 나름대로의 선을 정해놓고, 그 범위 안에서 "적당한 물타기"를 시도하게 됩니다. 
 멀티스레드 프로그래밍을 할 때 제 나름대로의 동기화 기준을 공개한다면 대략 다음과 같습니다.

1. 전역 데이터에 멀티스레드가 읽기를 동시에 시도하는 경우에는 동기화 할 필요가 없습니다. 

2. 전역 데이터에 멀티스레드가 읽기와 쓰기를 혹은 쓰기와 쓰기를 동시에 시도하는 경우에는 "원칙적으로" 직렬화를 시켜야 합니다. (직렬화를 한다 함은 동시접근을 차단한다는 뜻입니다.) 이때, 저는 읽기 및 쓰기가 행해지는 데이터의 성격에 따라 다음과 같이 "적당한 대처"를 합니다. ^^
   1) 멀티CPU 환경에서는 기본적으로는 4바이트 정수 연산 하나에 대해서도 원자성을 100% 보장할 수 없습니다. 따라서 동기화의 비용(성능 감소)와 데이터 무결성이 깨어졌을 때의 발생가능한 손해를 비교하여 동기화 수준을 결정해야 합니다.
   2) 포인터 데이터에 대한 무결성 문제는 바로 메모리 폴트로 이어집니다. 따라서 대상 데이터 중에 "포인터"가 포함된 경우에는 반드시 동기화를 시켜야 합니다. 
   3) 단순한 정수/실수형의 경우 "대부분의 경우"에는 동기화에 신경쓸 필요가 없습니다. 하지만 이 데이터가 무결성에 얼마나 민감한지를 검토해볼 필요는 있습니다. 예를 들어, 어떤 일을 해야 할지 말지를 나타내는 Boolean (True/False) 값 등은 굳이 동기화할 필요가 없습니다. 만약 어떤 값을 카운트하는 변수일 경우, 카운트가 1~2개정도 어긋나면 어떤 문제가 생길지를 체크해봅니다. 만약 ++연산을 100번했을 때 99만 증가해도 큰 문제가 되지 않는다면 동기화하지 않아도 되겠지만, 정확한 카운트가 보장되어야 하는 경우라면 해당 변수를 Volatile 로 선언한 후 InterlockedAdd 함수 등을 이용해 동기화해주어야 합니다.
   4) Linked List, Binary Tree 등의 자료구조는 각 Entry들이 포인터로 연결되어 있습니다. 따라서 반드시 동기화해주어야 합니다. STL도 예외는 아닙니다. 다만, Linked List에 Entry가 Insert, Delete되지 않는다면 (포인터 연산이 일어나지 않기 때문에) 동기화가 필요하지 않을 수도 있습니다.
   5) 구조체나 클래스, 배열 등의 경우에는 각 Entry 의 데이터 타입이나 성격에 따라 위의 1)~3) 기준에 따라 판단해주면 됩니다.
   6) Memory Mapped File 등 프로세스간 공유되는 데이터의 경우에는 가급적이면 동기화해주는 것이 좋습니다.

3. 요즘에는 그런 일은 거의 없겠지만, 멀티CPU에서 실행되지 않는다는 것이 보장된다면... 사실 왠만한 동기화는 신경 안써도 됩니다. 뒤집어서 말하면... 멀티CPU에서는 동기화에 대해 깊이 고민해야 합니다.


다음번에는 각 케이스 별로 데이터 무결성을 보장하면서 성능 저하를 최소화하는 동기화 방법(구조)에 대해 생각해 보려고 합니다.


'프로그래밍 > System program' 카테고리의 다른 글

멀티스레드에 관하여 2  (0) 2013.04.22
mmap  (0) 2013.04.21
//
프로그래밍/System program 2013. 4. 21. 03:36

void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

파일이나 디바이스를 응용 프로그램의 주소 공간 메모리에 대응시킨다.

 

1인자 => 시작 포인터 주소 (아래의 예제 참조)

2인자 => 파일이나 주소공간의 메모리 크기

3인자 => PROT 설정 (읽기, 쓰기, 접근권한, 실행)

4인자 => flags는 다른 프로세스와 공유할지 안할지를 결정한다.

5인자 => fd는 쓰거나 읽기용으로 열린 fd값을 넣어준다.

6인자 => offset은 0으로 하던지 알아서 조절한다.

 

int munmap(void* start, size_t length);

할당된 메모리 영역을 해제한다.

 

1인자 => 위에 mmap으로 지정된 포인터값 넣어주고

2인자 => 위에서 사용했던 length와 동일하게 넣어준다.

(왜냐면.. 할당했던거 동일하게 해제해야 하니깐..)

 

더 자세한 사항은 man page에 모든게 나와있음.

 

==============================================================

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include "sys/types.h"
#include "sys/stat.h"
#include "sys/mman.h" /* mmap() is defined in this header */
 
int main (int argc, char *argv[])
{
    int fdin, fdout;
    char *src, *dst;
    struct stat statbuf;
 
    if (argc != 3) {
        printf("usage: a.out <fromfile> <tofile>\n");
        return -1;
    }
 
    /* open the input file */
    if ((fdin = open (argv[1], O_RDONLY)) < 0) {
        printf ("can't open %s for reading", argv[1]);
        return -2;
    }
    /* open/create the output file */
    if ((fdout = open(argv[2], O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR)) < 0) {
        printf ("can't create %s for writing", argv[2]);
        return -2;
    }
 
    /* find size of input file */
    if (fstat (fdin,&statbuf) < 0) {
        printf ("fstat error");
        return -2;
    }
 
    /* go to the location corresponding to the last byte */
    if (lseek (fdout, statbuf.st_size - 1, SEEK_SET) == -1) {
        printf ("lseek error");
        return -2;
    }
 
    /* write a dummy byte at the last location */
    if (write (fdout, "", 1) != 1) {
        printf ("write error");
        return -2;
    }
    /* mmap the input file */
    if ((src = mmap(0, statbuf.st_size, PROT_READ,
                    MAP_SHARED, fdin, 0)) == (caddr_t) -1)
    {
        printf ("mmap error for input");
        return -2;
    }
 
    /* mmap the output file */
    if ((dst = mmap(0, statbuf.st_size, PROT_READ | PROT_WRITE,
                    MAP_SHARED, fdout, 0)) == (caddr_t) -1)
    {
        printf ("mmap error for output");
        return -2;
    }
 
    /* this copies the input file to the output file */
    memcpy (dst, src, statbuf.st_size);
 
    munmap(src, statbuf.st_size);
    munmap(dst, statbuf.st_size);
 
    return 0;
} /* main */
/* The end of function */
</tofile></fromfile></fcntl.h></string.h></stdlib.h></stdio.h>
1
2
3
4
5
6
7
8
9
실행 후 결과 화면
$ ./a.out test test_out
$ ls -al
drwxr-xr-x  2 jeon jeon 4096 Jul 17 08:39 .
drwx------ 12 jeon jeon 4096 Jul 17 08:39 ..
-rwxr-xr-x  1 jeon jeon 6410 Jul 17 08:39 a.out
-rw-r--r--  1 jeon jeon 1844 Jul 17 08:39 mmap.c
-rw-r--r--  1 jeon jeon  469 Jul 17 08:29 test
-rw-------  1 jeon jeon  469 Jul 17 08:39 test_out

 

'프로그래밍 > System program' 카테고리의 다른 글

멀티스레드에 관하여 2  (0) 2013.04.22
멀티스레드에 관한 글  (0) 2013.04.22
//