라벨이 System Programming인 게시물 표시

fork와 vfork

fork는 새로운 프로세스를 만드는 리눅스 시스템 콜이다. fork로 인해 생성된 자식 프로세스와 부모 프로세스는 서로 별개의 메모리영역을 가진다. 하지만 자식프로세스가 생성될 때 아예 부모의 메모리를 copy하는 것은 아니고 실제로는 부모와 자식이 page를 공유하다가 부모,자식중 누군가가 특정 page에 대해 쓰기작업을 할 때 그 누군가를 위한 page의 copy가 발생한다.  그러면 부모 자식관계가 여러명이면 어떻게 될까? 그래도 똑같다. 커널 내부적으로 fork에 의해 맺어진 프로세스들 사이에 page의 공유에 대한 정보가 저장되있을테고 그 프로세스들중 한 명만 write를 하면 그 한 명을 위해 copy가 발생하고 이제 그 프로세스는 다른 page를 사용하게 되는 것이다. http://unix.stackexchange.com/questions/58145/how-does-copy-on-write-in-fork-handle-multiple-fork vfork는 예전에 fork가 내부적으로 COW를 사용하지 않을 때를 위해서 만들어졌다고 한다. (vfork는 vfork + execve 를 위한 fork의 최적화 버전이라고 한다.) https://wiki.kldp.org/HOWTO/html/Secure-Programs-HOWTO/avoid-vfork.html vfork는 마치 clone처럼 부모와 자식이 같은 메모리영역을 공유한다. (하지만 스택조차도 공유한다.) 하지만 vfork를 하게 되면 부모 process는 자식 process가 종료되거나 exec* 함수를 호출할 때 다시 수행이 재개된다. 이 때 주의할 점이 자식 process가 return혹은 exit함수를 통해 종료되서는 안되고, 무조건 _exit함수를 통해 종료되어야 한다는 점이다. 왜냐하면 vfork는 자식process가 부모process의 스택조차도 그대로 사용하기 때문에 자식process가 스택을 어지럽히면 부모process의 실행이 이상할 수 있...

Windows Vista 이상의 환경에서 Service에서 interactive process 실행하기.

Windows Vista 이상의 환경에서 LocalSystem account context에서 돌아가는 Service에서 interactive process를 실행하는 방법에 대해 포스팅해보도록 하겠다. 이것 저것 많은 자료를 보면서 이해했다 ㅠㅠ 일단 Windows에서의 세션, 스테이션, 데스크탑에 대해서 이해해야한다. http://www.brianbondy.com/blog/100/understanding-windows-at-a-deeper-level-sessions-window-stations-and-desktops  (원본) http://www.benjaminlog.com/160  (번역본) 위 링크를 일단 읽으면 세션, 스테이션, 데스크탑이 뭔지에 대해서 알 수 있다. 그리고  http://cappleblog.co.kr/m/post/241  이 것도 보면 좋을 것 같다. access token 에 대해서도 알아야한다. http://blogs.msdn.com/b/winsdk/archive/2009/07/14/launching-an-interactive-process-from-windows-service-in-windows-vista-and-later.aspx 그리고 위 링크에서 내가 오늘 포스팅하려는 내용에 대해 설명하고 있다. 좀 더 친절하게 정리해서 내가 써보려고한다. 1. 현재 로그인하고 있는 다른 유저와 상호작용하는 process를 실행하고 싶은 경우   우선 로그인하는 있는 다른 유저가 로컬이라고 가정을 해보겠다. 서비스는 세션0에서 동작하고 있다. 그렇기 때문에 직접적으로 현재 로컬에서 로그인하고 있는 다른 유저의 세션에 접근할 수는 없다.  그래서 일단   WTSGetActiveConsoleSessionId   () 를 통해서 로컬에서 로그인되 '활성화' 되어 있는 유저의 세션id를 얻어야한...

Overlapped IO 할 때 주의해야 할 점.

이미지
Overlapped IO 를 할 때는 무조건 OVERLAPPED 구조체의 Offset, OffsetHigh 에 file offset을 넣어줘야한다.   1번째는 여러개의 IO가 동시에 진행되니까 당연히 OVERLAPPED 구조체의 Offset을 통해 IO가 진행될 file offset을 당연히 지정해줘야만 하다고 생각하였다. 하지만 2번째의 경우에는 각각의 IO가 동시에 1개씩 밖에 실행이 안된다. 즉 비동기 IO가 동기화되어있는 셈이다. 따라서 그냥 Offset에 0을 넣어도 상관없을거 같기도하고 아닌거 같기도 하고 해서 직접 실험을 해보았다. 실험 결과 2번째도 1번째랑 똑같은 결과가 나왔다. 즉 OVERLAPPED구조체의 Offset은 말그대로 파일 오프셋을 의미하는 것이였다. 나는 가장 최근의 비동기IO가 완료된 시점의 파일 오프셋을 Base로 했을 때의 Offset을 의미하는 게 아닐까 생각했었는데 아니였다. 그냥 파일 오프셋 자체였다. 정리하자면  Overlapped IO 를 할 때는 무조건 OVERLAPPED 구조체의 Offset, OffsetHigh 에 file  offset을 넣어줘야한다.

Windows Asynchronous Notification IO Model

Asynchronous Notification IO Model 이란 IO의 notification이 비동기로 이루어지는 것. 즉 IO이벤트 발생을 비동기적으로 확인하는 모델이다. 즉 IO이벤트 관찰 함수를 호출하는 시점과 IO이벤트 확인의 시점이 다른 비동기적인 모델이다. (내 생각에)  리눅스의 epoll과 거의 흡사하다. (코드도) 근데 사용하기는 epoll이 더 편하지 않나 싶다. select는 Synchronous Notification IO Model 이다. 근데 중요한 게 select를 Asynchronous Notification IO Model로 착각하면 안된다. 물론 select의 timeout을 0으로 둬서 비동기방식으로 사용할 수는 있지만 이는 select자체를 생각해볼 때 옳지 않은 방법이다. select는 매 함수 호출마다 file descriptor들의 event를 등록해야하는데 만약 비동기방식처럼 사용하려면 매우 비효율적이기 때문이다. (IO event가 발생하지 않았을 경우 다시 file descriptor들의 event를 등록해야하기 때문) 따라서 select는 asynchronous방식처럼 사용할 수는 있지만 비효율적이고, 애초에 생겨먹은(?)게 Synchronous이다. 그에 반에 epoll과 윈도우의 WSAEventSelect/WSAAsyncSelect같은 경우는 비동기 notification IO model 이다. select와 달리 관찰할 file descriptor 혹은 handle을 한번만 등록해 놓고 다른 일을 하다가 IO notification을 확인 할 수 있기 때문이다. 즉 epoll과  윈도우의 WSAEventSelect/WSAAsyncSelect 는 IO notification의 관찰을 비동기로 명령해놓고, 다른 일을 하다가 IO event의 확인을 해볼 수 있기 때문에 Asynchronous Notification ...

The reason why using non-blocking fd in edge triggered epoll

오랜만에 다시 epoll보니까 헷갈려가지고 정리해봅니다. level triggered 방식에서 read할 경우에는 buffer에서 전부 read하지 않아도 다음 epoll_wait에서 또 이벤트가 등록되기 때문에 다시 read할 기회를 얻을 수 있다. 그러나 edge triggered 방식에서는 input buffer에 data가 수신됬을 때만 read할 기회를 갖기 때문에 EAGAIN일때까지 계속 반복해서 수신을 해줘야한다. 이 때 만약 file descriptor가 blocking mode라고 했을 때, read할 data가 buffer에 없으면 read는 blocking 상태에 빠지기 때문에 문제가 된다. 따라서 edge triggered 방식에서는 반드시 file descriptor가 non-blocking mode 여야만 한다. 그래야지만 read가 위의 상태에서도 blocking상태에 빠지지않고  EAGAIN을 errno에 넣어주면서  바로 반환되어서 수신이 끝났다는 것을 알아차릴 수 있다. 이러한 edge triggered 방식의 특징때문에 edge triggered 방식의 epoll에서는 반드시 file descriptor가 non-blocking mode이여야만한다.