상세 컨텐츠

본문 제목

090604

청강컴정/시스템프로그래밍

by luckey 2009. 6. 4. 11:26

본문

동기가 깨질경우

시기를 놓침(왜 놓쳤을까?)
원인은 USB Driver에 있다.
명령을 보내야지만 너무 많이 지나버려서 다음번 프레임에 명령을 보내다 보니까

데이터 전송이 안되었다.
이전 신호가 끝나야지만 다음 신호를 보낼 수 있다.(전송의 누락현상)
Windows에는 IoStartPacket()[맡긴다는 명령] 라는 명령이 있다.
IRP를 처리(전달)하는 과정중에 IRP를 받은 대상이

IRP Dispatch()가 받았다.(받아서 독자적으로 처리하지 말고 드라이버는 IRP를 IO Manager에게 맡긴다.)
IRP Manager는 받은 IRP를 Queueing 하게 된다.
적절한 시기에 IRP Manager는 IRP를 꺼내서 Driver에게 전달하게 되며
Driver에서  IRPStartIO()[부른다.]에서 처리하게 된다.

IoStartNextPacket() : 다음 IRP를 달라는 명령


pending 처리된다.
미리 얼마든지 IRP를 보낼 수 있다.
명령을 받아서 바로 처리할 수 없거나 시기를 놓치는 현상이 발생하기 때문에 IRPStartIO()방식을 선호한다.

Queue는 클 필요가 없다.
포인터끼리의 연결관계를 가지므로 크기는 상관이 없다!!

 

ReadFile
WriteFile

IRP를 받았을때나 끝날때의 stack의 위치는 같아야 한다.!!!


Set Event(시그널만 발송 - 함수를 호출하는 것이 아니고 신호만 발생한다.)

HardWare가 언제 종료가 될 지 모르기 때문에 CPU는 다른일을 처리하고 있다.
깨울수 있는 유일한 방법은 Set Event밖에 없다.!!!

449page

STATUS_MORE_PROCESSING_REQUIRED : 현재 IRP가 더 처리할 일이 남아있으니까 그냥 포기해라
다시 보낼 일을 구상할 수도 있고 IRP를 소유할 수 있다.
처리된 일이 마음에 안든다. 다시 돌려보내기 위해서는 소유하고 있어야 한다.

462page
배경 : 타임아웃(지금부터 이시간까지 처리되야 한다.)
주기적인 타이머
BuiltIn Timer - IoInitializeTimer, IoStartTimer, IoStopTimer
매 1초마다 호출가능하다.(진짜 시간을 표시할때 사용가능하지만 사장되어 가고 있다.)
사용하기가 쉽다.

Custom Timer - KeSetTimer, KeCancelTimer
시간주기를 마음대로 바꿀 수 있다.
BOOLEAN
  KeSetTimerEx(
    IN PKTIMER  Timer,
    IN LARGE_INTEGER  DueTime,
    IN LONG  Period  OPTIONAL,
    IN PKDPC  Dpc  OPTIONAL
    );

    1ns(nano Second) 1/10^7

DueTime (처음 타임아웃)
Specifies the absolute or relative time at which the timer is to expire.
If the value of the DueTime parameter is negative, the expiration time is relative to the current system time.
Otherwise, the expiration time is absolute. The expiration time is expressed in system time units (100-nanosecond intervals).
Absolute expiration times track any changes in the system time; 절대값(양수) : 정확한 시간에 깨워라
relative expiration times are not affected by system time changes. 상대값(음수) : 지금으로부터 일정시간이 지나면

Period (반복주기) - 안써도 된다.(주기성의 타이머는 쓰지 않겠다.)
Specifies an optional period for the timer in milliseconds. Must be less than or equal to MAXLONG.
- 맨 처음 Timer는 DueTime에 호출되며 다음부터는 Period때에 발생된다.

어플리케이션에서 사용하는 타이머는 정확한 타이머가 아니다.
왜?? 메시지 기반이기 때문에... 메시지를 가져오는 시간에 달려있다.
메시지를 가져오는 시간이 빠를수록 정확하지만 느릴수록 부정확하다.

LONG : 4Byte
LARGE_INTEGER : 8Byte


--32bit (64bit는 X2)
PVOID pPointer; : 4byte
unsigned char * pPointer : 4byte
unsigned long * pPointer : 4byte
Large_Integer * pPointer : 4byte

64bit에서는 형변환이 되지 않는다.
ULONG dwTemp; : 4byte이지만
dwTemp = (ULONG)pPointer; : pointer는 8byte이기때문에...


474Page
Thread
System Thread - 이름이 System Process 이기 때문에 System Thread 이다.
모두 IRQL_PASSIVE_MODEL이 보장된다.

IRP -> IoCallDriver()
PASSIVE_LEVEL <= IRQL <= DISPATCH_LEVEL
DISPATCH_LEVEL : IDLE스케쥴러가 작동중에 있을때
IoCallDriver()는 PASSIVE_LEVEL <= 여기서 전달된다. <= DISPATCH_LEVEL

항상 PASSIVE_LEVEL이 보장되야 PASSIVE_LEVEL에서 사용되는 함수를 사용할 수 있다.
왜? 어디서 실행될 지 모르기 때문에
그래서? PASSIVE_LEVEL을 보장받기 위해서 Thread를 사용한다.

PsCreateSystemThread() 를 이용해서 Thread를 만든다.
WorkItem루틴 : 직접 Thread를 만들지 않고 호출될 함수를 알려준다. 만들어진 Thread를 이용한다.
만들어진 Thread는 자원활용에 비효율적이다. 오랜시간 Thread를 잡고 있으면 안된다.
WorkItem을 이용할경우의 Thread는 자기것이 아니다. 하지만 직접 Thread를 만들면 자기것으로 활용할 수 있다.

488page
i8259A PIC 칩에서 수용할수 있는 신호는 모두 8개 까지 처리할 수 있다.
PCI PIR에서 총 4개의 신호가 들어가기 때문에 ISA Device는 극히 유한적일수 밖에 없다.

PCI PIR은 각각의 PCI카드의 PCI Function신호를 모아서 가지고 있게 되며 이를 4개로 i8259A PIC 에 전달하게 된다.

8개는 충분하지 않기 때문에 사용에 제한이 있을 수 밖에 없다.
i8259A라는 칩은 존재하지 않지만 APIC(Advenced PIC)가 그 역할을 해준다.
하나당 256개까지 처리가 가능하다.
APIC가 필요하게 된 이유는 듀얼코어(멀티 프로세싱)이 나오면서 부터이다.

490page
CPU를 운영체제가 하나만 쓸경우에는 EQUIVALENT PICS를 이용해서 하나만 있는것처럼 가상화 한다.

491page
듀얼코어를 사용하는 CPU
LOCAL APIC는 CPU별로 전담
I/O APIC는 주변장치
원하는 대로 전담할 CPU를 결정할 수 있다.

493page
Hardware Abstraction Layer : 하드웨어를 추상화 한다.
추상화한다 Kernel에게 컴퓨터를 커널에게 추상화 한다.
추상화 계층이 필요한 이유 : 커널이 없으면 직접 건드려야 한다. (코드의 호환성이 떨어진다.)
다양한 플랫폼 지원(단일 CPU, 듀얼 CPU등등...)

커널이 관심을 가지는 하드웨어
1. Interrupt
2. realTime clock : 시간을 정확히 알아야 한다.
3. serial port, 1394port (디버깅용으로 부팅시)

497page 그림 외우기
1. interrupt신호 발생
2. cpu는 주소를 구해온다.(interrupt disc~)
3. 그 주소를 취해서 그 주소까지 이동한다.
4. 그 주소에는 커널이 있다.
5. HalBeginSystemInterrupt() ISR루틴을 구해서

공유ISR : PCI에서 내보내는 것들
공유되어 있기 때문에 누가 부른건지 알수 없다. 모두 불러서 확인한다.

비공유ISR

HalEndSystemInterrupt() 를 이용해서 일을 마친다.


501page

503page
DPC :

512page
ListEntry(양방향 링크드 리스트)
BLink(Backword Link) - 후방향
FLink(Forward Link) - 전방향

BLink와 FLink가 가리키는 지점이 같으면 아무도 연결되어 있지 않다는 뜻이다.
InitializeListHeader()함수를 이용한다.

어디다 붙일 것인가??
InsertHeadList()함수를 이용해서 붙일 수 있다.

Flink 관점 ListHead -> ListHead #1 -> ListHead #2
Blink 관점 ListHead -> ListHead #2 -> ListHead #3

InsertTailList(꼬리에 붙인다.)

동기화문제?
듀얼 동기화 조건에서는 Interrupt 명령을 호출

539page

관련글 더보기

댓글 영역