2015의 게시물 표시

Visual Studio C++ Native Unit Test 짱

이미지
Visual Studio C++에서 Native Unit Test를 이용해보았다. 짱 좋다! method혹은 class 별로 Unit Test를 하는 습관을 길러야 겠다~ 기억할 것) 1. 테스트 프로젝트 (테스트할 프로젝트)가 export하는 class, function등에 대해서만 테스트 가능한 것 같다. (테스트 프로젝트의 구성형식을 .lib로 바꾸면  된다! 근데 안바꾸고도 할 수 있는 방법 없으려나?? ㅠㅠ .obj 을 다 인클루드하는 것 불편하고,,,another project와 함께 unite되서 build되는 그런 거 없나??? ㅠㅠ) 사진들------------------------- Unit Test 코드이다. testcase를 생성해서 test를 진행하면 된다. Assert::??? 를 이용해서 test성공여부를 결정할 수도 있다. 테스트를 하면 이렇게 테스트 성공 여부와 경과 시간이 뜬다. 테스트 출력 결과도 볼 수 있다~

Key가 있어야만 생성가능한 클래스만들기.

이미지
다음과 같은 상황을 가정하자.  특정 객체의 직접 생성을 막고 오직 factory function을 통해서만 객체를 생성할 수 있도록 하게 하려고 한다. 이럴 경우는 생성자를 private로 선언하고 클래스내의 factory function에서 private인 생성자를 호출하면 된다. 즉 위와 같이 작성하면 충분하다.  그런데 C++11에서 std::vector의 emplace_back, std::make_shared같이 내부적으로 arguments를 forwarding하여 생성자를 호출하는 함수를 사용할 경우에는 생성자가 private이기 때문에 위의 코드는 컴파일에러를 띄운다. 그렇다고 생성자를 단순히 public으로 놔버리면 초기의 목표에 모순이 된다.  첫번째 해결책으로 friend keyword를 떠올릴수있다. 그러나 이것은 일반적이고 쉬운 해결책은 아닌 것 같다. 일단 나의 경우 std::make_shared 에 friend선언을 하기 위해서 정보를 찾아봤는데 컴파일러버전마다 friend 선언이 달라진다고 한다. make_shared 외에 다른 것들에 대해서는 확인해보지 않았지만 일단 make_shared 만으로 제너럴하게 적용할 수 없기 때문에 좋은 방법은 아닌 것 같다. 그리고 일일히 friend 선언을 해줘야하므로 성가시고 귀찮다고 할 수 있다.  그래서 두번째 해결책을 소개하려고 한다. 이 것은 일종의 PrivateKey(HiddenKey) Class를 이용하는 방법이다.  코드를 그냥 보는 것이 이해가 빠를 것이다. A의 진짜 생성자(A())는 private로 감춰져있다. 하지만 A()로 리다이렉트되는 A(PrivateKey) 생성자가 public으로 공개되어있다. 하지만 PrivateKey가 있어야만 입장가능(?)하다. 하지만 PrivateKey는 private임으로 자기맘대로 가질수는 없다. 따라서 외부에서는 PrivateKey를 얻을 수 없기때문에 A객체를 생성할 수 없고, A

[공지] 카톡 오픈채팅방을 만들었습니다!

카카오톡에 오픈채팅방이라는 기능이 생겼더라고요~ 익명으로 그룹 혹은 1:1채팅을 할 수 있데요 ㅎㅎ 그래서 저도 한번 만들어봤습니다~ 혹시 블로그 방문하시는분들 중에 포스팅한것에 대해 궁금한 점이 있거나 저랑 얘기나누시고 싶은 분은 이용하시면 좋을 것 같아요~~ https://open.kakao.com/o/sgjqqkf (1:1) https://open.kakao.com/o/gmr4pkf (단체)

Hack the PXE booting!

인터넷에서 우연찮게 아래의 기사를 보게 되었다. http://dailysecu.com/news_view.php?article_id=12221 기사의 내용은 PXE 부팅과정에서 이미지를 바꿔치기 하는 식으로 해킹이 가능하다는 것 이다. 마침 학교에서도 랩실 컴퓨터를 포멧할때 PXE를 활용하기 때문에 관심이 갔다. 그래서 어떤식으로 해킹이 이루어질지 생각해 보았다. 일단 PXE 부팅은 내부적으로 dhcp와 tftp 프로토콜을 이용한다. 일단 DHCP client가 먼저 동작해서 ip와 몇 가지 추가정보를 얻게 된다. 그리고 추가정보를 이용해서 tftp client가 tftp server에서 이미지 파일을 수신하고 부팅하게 된다. ( http://blog.pages.kr/156 ) 즉, 해킹을 하려면 dhcp spoofing을 이용해서 PXE booting을 시도하는 PC를 속이고, PC가 해커가 의도한 server로 부터 이미지를 수신받게 하면 되는 것이다. 아래링크는 DHCP spoofing과 방어기법 DHCP snoofing에 관련된 글이다. http://ryusstory.tistory.com/entry/DHCP-Snooping-Prevent-DHCP-Starvation-Attacks PXE spec 문서를 보면 자세한 내용을 알 수 있다. http://www.pix.net/software/pxeboot/archive/pxespec.pdf 위 문서의 13페이지를 보면 PXE Boot 과정에 대한 그림과 설명이 나와있다. DHCP Server와 통신후 Boot Server와 통신하는 것을 알 수 있다. 14페이지의 Step3를 보면 "The Boot Server list from the Boot Server field in the PXE tags from the DHCPOFFER." 란 부분을 볼 수 있다. 즉 이를 통해 hacker는 DHCP가 unauthorized 하다는 점을 이용해서 실제 dhcp서버보다 먼

new보단 make_shared를 사용하자. (but not always)

C++11에서는 총 3가지의 smart pointer를 지원한다. (shared_ptr, unique_ptr, weak_ptr) 이 때 make_shared를 사용할 때는 std::shared_ptr<T> ptr(new T(a,b,c)) 보다는 std::shared_ptr<T> ptr = std::make_shared(a,b,c); 를 사용하는 것이 좋다. 그 이유는 전자의 경우에는 actual object를 생성하고, control block이 따로 생성되는데 후자의 경우에는 내부적으로 actual object와 control block을 함께 생성하기 때문이다. 따라서 후자가 좀더 효율적이라고 할 수 있다. new의 호출 횟수만 봐도 전자는 2번, 후자는 1번이다. 그리고 후자의 경우가 당연히 locality와 memory fragmentation의 측면에서 더 좋다. 그러나 무조건 좋은 것만은 아니다. 전자의 경우에는 reference count가 0이 되면 actual object가 소멸되고, weak reference count 마저 0이 됐을 때 control block이 소멸되지만, 후자의 경우에는 reference count와 weak reference count가 모두 0이 됐을 때 비로소 actual object와 control block이 함께 소멸되게 된다. http://itability.tistory.com/37 를 보면 장단점에 대해서 좀 더 알 수 있을 것이다. (이 블로그의 modern c++카테고리에 C++팁이 잘 정리되어있는 것 같다. ) http://egloos.zum.com/hellpme/v/1543080 를 보면 어떤 사람이 실제로 성능을 비교한 결과가 있다. 만약 최적화를 하지않았을 때 오히려 new보다 make_shared가 느린 이유는 make_shared의 경우에는 move constructor가 추가로 호출되기 때문인 것 같다. (~~ ptr = ~~ 이니까)

C++ 2D subscript overloading using typecasting.

이미지
C++에서 연산자오버로딩을 이용하면 코드의 가독성을 좋게 만들 수 있고, 좀 더 편하게 객체를 사용할 수 있게 된다. 예를 들어 Array 클래스가 있을때, Array array; .... n = array.get(10); // 1 n = array[10]; // 2 두 가지 방법중 subscript overloading을 이용한 2번 방법이 보기 편하고 직관적일 것이다. 만약 2D subscript overloading, 즉 [][] 연산자를 overloading하려면 어떻게 해야할까? 실제로 [][] 연산자는 존재하지 않고, [] 가 2번 연산된 것으로 처리된다. 따라서 이를 수행하려면 http://stackoverflow.com/questions/6969881/operator-overload 와 같이 Proxy Class를 이용해야한다. Proxy객체를 이용하면 생성하고 초기화하고 소멸하는 등에 대한 추가적인 overload가 든다. 오늘 그래서 내가 생각해낸 방식이 Imaginal Proxy Class 라는 방법이다. (이름은 내가 지었다..) Proxy Class는 사용하되 객체는 생성하지말고, type casting을 이용해 Proxy Class의 subscript operator만 사용하게끔하는 것이다. 아래가 그 예이다. 음?? 왜 이거 짤때 *reinterpret_cast<PixelArray*>~~ 이런식으로 했지?? 포인터쓸 필요없이, 그냥 레퍼런스 이용해서 reinterpret<PixelArray&>(data[idx * width]) 이런식으로 하면 됩니다 ㅋㅋㅋㅋ 위에서 PngImage가 우리가 2D subscript operator overloading을 하려는 대상이고, PixelArray가 그 것을 위한 Proxy Class이다. PngImage::data에 pixel정보들이 차례로 나열되어 있다. Image와 PixelArray의 operator[]를

가상화와 에뮬레이션, hypervisor, container

일단 에뮬레이션(Emulation)과 가상화(Virtualization)에 대해 알아보자. 에뮬레이션과 가상화 둘다 가상적으로 특정 시스템이 돌아갈 수 있게 하는 것이지만, 에뮬레이션은 기존의 리소스나 하드웨어를 이용하지 않고 소프트웨어적으로 구현하여 특정 시스템을 돌릴 수 있게 하는 것이다. 반면 가상화는 기존의 리소스나 하드웨어를 활용하여 시스템을 돌릴 수 있게 한다. 따라서 성능적인 면에서 가상화가 에뮬레이션보다 뛰어나지만, 가상화가 에뮬레이션보다 범위가 한정되있다고 할 수 있다. 에뮬레이션을 이용하는 것으로는 대표적으로 bochs, qemu가 있다. https://powermore.dell.com/technology/emulation-virtualization-whats-difference/  다수의 운영 체제를 동시에 실행하기 위한 논리적 플랫폼을 하이퍼바이저(hypervisor)라고 하는데, 두가지로 분류할 수 있다.  첫 번째는 native이다. 이는 호스트OS없이 VMM이 하드웨어 위에서 직접 동작하고, 그 위에 여러개의 가상머신(OS+APP)이 동작하는 방식이다. 즉 하드웨어를 가상화하게 된다. VMware ESXi가 이에 해당한다. 이 경우에는 물리적cpu와 가상머신의 cpu가 architecture가 같아야하는등 하드웨어상의 제약이 생긴다. hosted에 비해 당연히 빠르다.  두 번째는 hosted이다. 이는 호스트OS 위에서 VMM이 동작하는 방식이다. 따라서 이 경우는 물리 컴퓨터의 하드웨어를 에뮬레이트하게 된다. 즉 하드웨어를 에뮬레이션하게 된다. 예를 들면, VMware WorkStation, VirtualBox, Qemu등이 이에 해당한다. 이 경우 호스트pc와 가상머신의 cpu architecture가 같냐 다르냐에 따라 속도가 크게 차이난다. (cpu를 에뮬레이트해야하냐 안해야하냐의 차이가 나므로..) https://superuser.com/questions/447293/does-qem

클라우드 서비스 IaaS, PaaS, SaaS, ASP

 IaaS, PaaS, SaaS 모두 클라우드기반으로 서비스를 제공하지만 무엇을 제공하냐에 따라 나뉜다.  IaaS는 Infrastructure 즉 인프라를 제공한다. 예를 들면, Amazon EC2과 같은 클라우드 컴퓨팅 서비스가 IaaS에 해당한다. 하드웨어나 네트워크에 대한 관리부담을 갖지않고, OS를 포함해 그 상위 레벨에 대해서만 관리를 하면 된다.  PaaS는 Platform을 제공한다. 개발을 위한 플랫폼과 프레임워크등을 제공한다. 예를 들어, Azure나 오픈API등이 이에 해당한다. PaaS를 이용하면 개발자들이 OS나 플랫폼에 대한 부담없이 개발자체에 집중할 수 있다.  SaaS는 Software를 제공한다. SaaS를 이용하면 Software가 동작되고 구동되는데에 대한 어떠한 내부적인 이해없이 단순히 Web등을 통해 Software를 사용할 수 있다. 구글 App이 이에 해당한다. http://blogs.msdn.com/b/eva/archive/2012/01/16/on-premise.aspx http://www.itworld.co.kr/news/80349 http://www.sqler.com/471632 http://www.hostway.co.kr/support/faq/iaas-paas-saas%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94  SaaS와 ASP(application Service Provider)의 차이점에 대해서 생각해보자.  ASP는 단순히 소프트웨어가 네트워크를 통해 서비스되는 것을 말한다.  즉, 기존의 소프트웨어가 개인 PC에 설치되어 서비스되었다면, ASP는 Web등을 통해 네트워크를 통해 서비스되는 걸 말한다.  SaaS는 ASP보다 진화된 형태라고 볼 수 있을 것 같다. 예를 들면, ASP는 고객마다 instance를 하나씩 띄운다고 하면, SaaS는 하나의 instance를 통해 다수의 고객을 서비

OOP in C

이미지
C에서도 객체지향적으로 코딩을 할 수가 있다.  하지만 C자체적으로 객체지향을 위한 키워드나 문법을 지원하지 않으므로 억지스럽고 비효율적인 측면이 있고 불가능한 부분도 존재한다. 객체지향의 핵심은 무엇일까? 1. Class (데이터 + 메소드) 와 캡슐화 2. 정보 은닉 및 추상화 3. 상속 4. 다형성 난 이 4가지가 객체지향의 핵심적인 개념이라고 생각한다. 일단 C에서 Class (데이터 + 메소드) 와 캡슐화의 개념을 implementation 하려면 설계를 객체지향적으로 하면 된다. Class같은 경우는 데이터는 구조체 안에 넣고, 메소드는 구조체이름_메소드이름 (구조체 포인터, ...) 이런 형태로 하면 된다... 만약 함수포인터를 이용하면 C++같은 문법으로 메소드를 사용할 수 도 있겠지만... 객체 만들때마다 함수포인터들을 초기화해줘야하므로 별로인 방법 같다. 추상화나 정보 은닉 같은 경우는 파일 분할과 static을 이용하면 가능하다. 아래에 그 예제가 있다. blackbox.h blackbox.c main.c main.c에서 6번째줄의 주석을 풀면 위와 같은 에러가 난다. main.c입장에서는 struct blackbox가 있다는 것 만 알지,  struct blackbox 내부 구조를 모르므로  그 크기를 모르기 때문에  변수를 만들수가 없다. 따라서 포인터를 사용해야한다. 포인터는 무조건 크기가 정해져있으므로 타입에 상관없이 변수를 할당할 수 있다. main.c에서 11,12번째 줄의 주석을 풀면 위와 같은 에러가 난다. 위에서 설명한 바와 같이  struct blackbox 내부구조를 모르므로 dereferencing이 불가능하다. 따라서 11,12번째줄에서 에러가 난다. 실행결과는 위와 같다. 위 코드에서는 성공적으로 private variable과 private/public method, 그리고 생성자와 소

mutex, semaphore, conditional variable, monitor의 차이점

mutex, semaphore, conditional variable, monitor의 차이점에 대해 서술해보겠다. 참고로 아래의 내용은 특정 OS에 국한된 특수한 내용이 아니라 general concept에 대한 내용이다.   mutex는 locking mechanism이다. 즉 mutual exclusion을 위한 것으로서 lock의 owner가 존재한다. 교과서적으로는(이론적으로는) mutex와 binary semaphore를 같게 취급하는 경우도 있지만, 실제 implementation에서는 mutex는 ownership의 개념이 있다는 측면에서 다르다. binary semaphore는 누구나 up하고 down할 수 있지만, mutex는 lock의 owner만 release할 수 있다.   semaphore는 signal mechanishm이다. semaphore count가 0일 경우 non-signaled, 1이상일 경우 signaled상태라고 할 수 있다. 누구나 semaphore count를 up 혹은 down할 수 있다. semaphore는 mutex보다 general하게 사용될 수 있다. semaphore도 locking mechanism으로서 사용될 수 있겠지만 mutex를 사용하는 것이 좀 더 옳은 방법일 것이다.    semaphore는 생산자-소비자 모델에서 활용될 수 있을 것이다. 여러개의 생산자 thread, 여러개의 소비자 thread가 있을 때 생산자는 생산이 완료되면 semaphore를 up하고, 소비자는 소비를 하기전에 down하는 식으로 생산자-소비자 모델을 구현할 수 있을 것이다.   conditional variable은 특정 조건이 성립할 때까지 wait하고, 조건이 성립할 때 wait하고 있는 thread 1개 혹은 여러개를 깨울 수 있는 mechanism이다. conditional variable은 보통 mutex와 associated되어 사용된다. semaphore와 다른 점은 se

Pintos의 conditional variable implementation에서 semaphore list를 쓰는 이유

이미지
Pintos의 threads/synch.c 의 일부이다. Pintos에서는 conditional variable을 구현하기 위해 semaphore list를 사용한다. 근데 사실 semaphore 한 개만을 사용해도 괜찮아 보일 수 있다. 어차피 semaphore 자체적으로 waiter들을 list로 관리하고, queue처럼 사용되므로 semaphore list를 사용할 필요없이 한 개의 semaphore를 가지고 conditional variable을 구현해도 상관이 없어 보인다. 하지만 이렇게 되면 cond_wait가 호출 된 후 cond_signal이 호출 됬는데, 먼저 호출된 cond_wait에서 signal을 받지 못하는 경우가 있을 수 있다. 왜냐면 lock_release를 하고 sema_down을 하게 될 텐데, lock_release 직후에 다른 thread가 스케쥴링되고 그 thread에서 cond_signal하게 되면 semaphore에 waiter가 없으므로 sema_up을 하지 않을테고 먼저의 thread는 signal을 받지 못하는 경우가 생길 수 있다. 이것이 그렇게 critical한 문제일까? lock_release시에 lock을 기다리는 thread가 없는 경우라면 아마 대부분 sema_down으로 흐름이 이어질테니까 대부분의 경우에는 문제가 안생기고 가끔 문제가 발생할 것이다. 근데 lock을 기다리고 있고 lock을 얻은 후 cpu-burst동안 cond_signal을 호출 하는 thread가 있을 경우에는 cond_wait가 평균적으로 1개의 signal을 씹을 것이다. 즉 충분히 critical한 문제라고 할 수 있다. 하지만 만약 cond_wait에서 1개 정도의 signal은 씹혀도 크게 상관없는 상황이라면 한 개의 semaphore를 가지고 conditional varaible을 구현해도 상관이 없을 것이다. 여기서 한 개의 semaphore를 가진다고 해서 conditional varia

[Windows Via C/C++][13장] Page, Block, Region, Partition

Page와 Block과 Region, 그리고 Partition의 용어가 헷갈려서 정리를 해놓는다. Virtual Address Space  : Process가 사용할 수 있는 가상적인 주소 공간. Partion  : 프로세스의 가상 주소 공간을 분할시킨 것 (윈도우에서 가상 주소 공간은 4개로 분할된다 - NULL포인트 할당, 유저 모드, 64KB접근금지, 커널모드) Region  : VirtualAlloc을 통해 reserve혹은 commit된 가상 주소 공간. 혹은 연속된 free상태의 페이지들의 집합. Block  : 동일한 보호 특성을 가지고 동일한 형태의 물리적 저장소에 매핑된 연속된 페이지들의 집합 (동일한 보호 특성, 상태, 페이지 형태를 가진 인접하는 모든 페이지들의 집합) Page  : 가상 주소 공간을 일정한 크기로 나눈 것 (x86, x64에서 4KB, IA-64에서는 8KB이다..) 즉, 윈도우의 Virtual Address Space는 4개의 Partion으로 구분되고 각각의 Partion은 여러개의 Region으로 구분된다. 그리고 Region은 또 여러개의 Block으로 구분할 수 있고, 각각의 Block은 하나이상의 Page들로 이루어지게 된다.

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의 실행이 이상할 수 있기 때문이다. r

Data Alignment

CPU는 byte단위로 data를 읽는 것이 아니라 word단위로 data를 메모리에서 읽어들인다.  예를 들어 x86의 경우 32비트(4바이트)단위로 data를 읽어들이는데 이는 즉 0x0에서 0x3까지 4바이트를 읽어들이는 것은 한 번에 데이터를 읽어들일 수 있지만 0x1부터 0x4까지 4바이트를 읽어들이려면 0x0 ~ 0x3 , 0x4 ~ 0x7 이렇게 총 2 번 메모리를 읽어들여야 한다. 이러한 데이터를 비정렬 데이터라고 하는데 만약 비정렬 데이터를 들어들이려고 할 때 cpu의 동작은 cpu마다 다르다. 예를 들어, x86이나 x64같은 경우 cpu는 기본적으로 메모리 상에서 비정렬된 데이터에 대한 읽기 작업을 2개의 정렬된 위치에서의 읽기 작업으로 전환해서 수행한다. 즉 성능이 매우 안좋아지는 것이다. 하지만 예외가 발생하지는 않는다. 그러나 IA-64같은 경우는 비정렬 데이터에 접근하려고 하면 비정렬 예외가 발생하고 OS가 그 예외를 자동으로 처리해주거나 소프트웨어에 예외가 전달되게 된다. 그러면 x86기반에서 visual C++을 이용해 구조체를 사용하면 double같은 경우 8-byte로 alignment가 된다. 이는 왜 그런걸까? double(8-byte type)을 4-byte alignment하든 8-byte alignment하든 cpu는 2번 메모리에서 읽어들여야하는데 말이다. 그 이유는 바로 캐시라인 때문이다. 캐시라인의 크기는 cpu마다 다른데 Intel x86 cpu의 경우 cache line의 크기는 64byte이다. 만약에 double이 4-byte alignment된다고 가정하자. 그러면 double variable이 0x3C ~ 0x43에 위치하고, cache line 1이 0x0 ~ 0x3F , cache line 2가 0x40 ~ 0x7F 의 메모리 주소의 data를 가지고 있다고 생각해보자. 이 경우 double variable의 data를 읽으려면 cache line 1과 cache line 2

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를 얻어야한다.  그리고  WTSQueryUserToken  () 를 통해서 세션id

도메인에 자신이 만든 네임서버를 연결시킬 때 네임서버등록과 호스트등록이 둘 다 필요한 이유

이미지
나는 taeguk.me 라는 도메인을 보유하고 있는데 이 도메인에 내가 만든 네임서버를 등록하려는데 자꾸 호스트가 등록되지 않았다는 메시지가 뜨면서 실패하였다. 알고보니 도메인업체 사이트에서 호스트등록 메뉴에서 네임서버를 등록해야했다. 결국 ns.taeguk.me를 호스트등록함으로서 문제를 해결했다. 근데 왜 네임서버 등록은 왜 아이피주소가 아닌 ns.taeguk.me 와 같은 식으로 해야하고, 굳히 호스트 등록을 해야하는지 의문이 들었다. 이에 대한 해답은 nameserver 설정파일을 통해 답을 내릴 수 있었다.   위를 보면 .(루트)의 서브도메인에 대한 NS를 A,ROOT-SERVERS.NET. 과 같은 식으로 지정해주고 있는 것을 알 수 있다. 그리고  A,ROOT-SERVERS.NET. 의 Address를 198.41.0.4와 같은 식으로 지정하고 있다. 이때 NS를 지정하는 것은 도메인업체 사이트에서 "네임서버 설정" 에 해당하는 부분이고, NS에 대한 ip address를 A레코드를 이용해 지정하는 것은 도메인업체 사이트에서 "호스트 등록"에 해당하는 부분이다. 즉 taeguk.me. 도메인에 대해서 네임서버를 ns.taeguk.me.로 설정한다면 taeguk.me. IN NS ns.taeguk.me. 라는 세팅이 me. 도메인의 네임서버에 추가될 것이다. (아마?) 그리고 ns.taeguk.me. 에 대해 호스트등록을 한다면 ns.taeguk.me. IN A 123.123.123.123 라는 세팅이 me. 도메인의 네임서버에 추가될 것이다. (아마?) 그러면 왜 네임서버 등록에서 아이피주소로 등록할 수 없는 지에 대한 해답이 나온다. ip address는 A레코드에서만 설정할 수 있기 때문이다. 따라서 무조건 글루레코드를 이용해야만 하는 것이다. 그러면 만약 taeguk.me. 에 대한 네임서버가 ns.hello.com. 이라

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을 넣어줘야한다.

IIS에서 FTP열기 문제 (cuz passive mode, FTP 방화벽 지원)

IIS에서 ftp세팅을 하고나서 외부에서 연결을 하려고 하니 접속이 안됐다. 깜박하고 IIS에서 FTP방화벽 지원을 안한 것이다 ㅠㅠ IIS에서 FTP passive mode를 지원하기 위해서는 FTP 방화벽 지원에서 사용할 포트 범위를 설정하고, 인바운드 방화벽에서 그 포트범위에 대해서 허용규칙을 추가한다. http://livegs.tistory.com/33

[Windows Via C/C++][1장 에러 핸들링] FormatMessage가 format message를 얻는데 실패하는 경우

ErrorShow 예제 어플리케이션 코드를 보면 FormatMessage가 format message를 얻는데 실패했을 경우에 대한 처리가 있다. 실패할 수 있는 이유는 FORMAT_MESSAGE_FROM_SYSTEM 일때, 모든 error code에 대한 error message를 얻을 수 있는게 아니기 때문이다.  2번째 링크에서 알 수 있다시피 FORMAT_MESSAGE_FROM_SYSTEM에서 얻을 수 있는 것은 System Error Messages 뿐이다.  winerror.h에 모든 error code가 존재하지는 않는 것처럼 system message table에 모든 error message string이 존재하지는 않는다. 예를 들어 network error에 대한 error code는 lmerr.h에 정의되어있고 이에 대한 message table는 netmsg.dll에 있다. 따라서 책의 예제 코드에서  FORMAT_MESSAGE_FROM_SYSTEM  에서 실패 했을 경우에 netmsg.dll 의 모듈핸들을 얻어서 이를 이용해서 format message 획득을 시도해보는 것이다. 물론 책에 있는 예제도 완벽한 것은 아니다. 책의 예제프로그램에서는 netmsg.dll에도 없는 error message에 대해서는 출력해주지 못한다. http://blogs.msdn.com/b/oldnewthing/archive/2008/09/01/8914664.aspx https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx https://msdn.microsoft.com/ko-kr/library/windows/desktop/aa370285(v=vs.85).aspx https://www.rpi.edu/dept/cis/software/g77-mingw32/include/lmerr.h

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 IO Model이고, select는 함수 호

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이여야만한다.

Chrome Extension으로 강의평가 auto 프로그램 만들기...

이미지
우리 학교는 기말 성적을 보려면 강의평가를 해야한다. 근데 항목들이 수업내용과는 전혀 쌩뚱맞은 이상한 것들이여서 어차피 그냥 대충 좋음 정도로 다 클릭하는 편이다. 어차피 막 할 꺼 오토프로그램을 짜면 참 좋겠다는 생각이 들어서 Chrome Extension형태로 오토프로그램을 만들어 보기로 했다. 일단은 개발자도구를 이용해 강의평가 시스템을 분석했다. 1. 프레임들이 매우 단계적으로 쪼개져있다. saint포털 전체에서 내부적으로 여러개의 iframe이 존재하고 그안에 또 여러개의 iframe이 있고, 또 그안에 frameset/frame들이 있고... 이런 식이다... 2. 강의평가 radio button을 누를때마다, 서버로 data가 전송되고, frame이 reflesh 된다. 따라서 그냥 간단하게 나는 chrome extension에서 target frame에 접근하여 그 frame에서 getElementsByClassName 을 이용해서 radio button을 다 끍어서 체크하는 식으로 하려고 했다. 근데 chrome extension에서 security 상의 문제로 frame에 접근할 수 없었다. 참고로 chrome extension 에 대해 말하자면, 기본적으로 manifest.json 파일이 있고, 이 안에 program의 정보나 권한등을 집어넣는다. 그리고, html와 js를 통해서 program을 제작할 수 있는데, chrome extension과 web page는 서로 독립된 영역을 가진다. 따라서 각자의 code는 서로에게 영향을 끼칠 수 없다.(기본적으로는) 근데 chrome extension에서 web page의 DOM에 access 하고 싶을 때가 있다. 그 때 executeScript 라던지 content_scripts 를 사용하여 그렇게 할 수 있다. (content_scripts 를 사용하려면 permissions에 tabs를 꼭 추가해야함.) 어쨌든 다시 돌아와서 frame