우분투 12.04 에서 vmware 8.0.3 버젼을 설치한 후 처음 실행시키면  다음의 에러가 발생한다.


VMWare Virtual Network Devcie Error





http://weltall.heliohost.org/wordpress/2012/04/01/vmware-workstation-8-0-2player-4-0-2-and-7-1-x3-1-x-fix-for-linux-kernel-3-4-0/


위 링크로 가서 패치를 적용하면 위의 문제를 해결할 수 있다.



간단히 설명하자면 아래의 패치를 다운받은 후 적용하면 된다.


vmware802fixlinux340.tar.gz


먼저 아래 파일의 압축을 해제 한다.

$ tar xvzf vmware802fixlinux340.tar.gz


압축을 해제 하면 "patch-modules_3.4.0.sh" / "vmware3.4.0.patch" 파일 두 개가 생성 될 것이다.


vi 로 patch-modules_3.4.0.sh 을 편집한다.

vmreqver=8.0.2 => vmreqver=8.0.3 으로 변경한다.


변경 후 patch-modules_3.4.0.sh 패치를 실행하면, 패치 완료 된다.

$ sudo ./patch-modules_3.4.0.sh









svn 레포지터리 dump


$ svnadmin dump [repository directory path] > [repository.dump]


$ svnadmin dump -r [n] > [repository_n.dump]                    // 리비전 n부터 백업

$ svnadmin dump -r [n]:[m] > [repository_nm.dump]            // 리비전 n에서 m까지 백업



svn 레포지터리 적재


레포지터리 생성

$ svnadmin create [repository name]


데이터 적재

$ svnadmin load [repository name] < [repository.dump]








Windows 7


netsh -c "interface ipv4" set neighbors "로컬 영역 연결" (혹은 인덱스번호)  "000.000.000.000" (IP) "00-00-00-00-00-00" (MAC)


ex) netsh -c "interface ipv4" set neighbors "로컬 영역 연결" "192.168.1.1" "00-01-02-03-04-05"



이외 버젼


arp -s 000.000.000.000(IP) 00-00-00-00-00-00(MAC)


ex) arp -s 192.168.1.1 00-01-02-03-04-05


1. [UP System] 프로세스 컨텍스트 간의 동기화


semaphore, preempt_disable

semaphore는 CS(Critical Section)를 공유하는 프로세스 컨텍스트들을 휴면 시켜서 동기화를 달성한다. preempt_disable은 CS를 공유하는 프로세스 컨텍스트들은 물론이고 다른 모든 프로세스 컨텍스트들 또한 선점을 금지시켜 동기화를 달성한다. CS 구간이 긴 경우 semaphore를 짧은 경우 preempt_disable을 사용한다.


local_irq_disable을 사용할 수도 있겠지만 인터럽트 컨텍스트가 없기 때문에 불필요하다. 프로세스 컨텍스트는 휴먼 가능 하므로 spin_lock은 사용 불가능하다.



2. [UP System] 프로세스 컨텍스트와 인터럽트 컨텍스트 간의 동기화


local_irq_disable

local_irq_disable은 모든 인터럽트를 금지 시키기 때문에(심지어 타이머 인터럽트에 기반한 스케줄러까지) CS를 공유하는 프로세스 컨텍스트와 인터럽트 컨텍스트 간 동기화를 달성한다.


인터럽트는 스케줄링 대상이 아니므로 semaphore, preempt_disable로는 프로세스 컨텍스트와 동기화를 달성할 수 없다. 또한 semaphore는 휴면 가능하므로 인터럽트 컨텍스트에서는 아예 사용이 불가능하다. 인터럽트 컨텍스트는 항상 프로세스 컨텍스트에 우선 하므로 spin_lock은 사용 불가능하다.



3. [UP System] 인터럽트 컨텍스트 간의 동기화


local_irq_diisable

인터럽트 컨텍스트는 스케줄링 대상이 아니므로 local_irq_disable로 동기화를 달성한다.


인터럽트는 우선순위에 따라 중첩이 가능하므로 spin_lock 사용 불가능하다.


semaphore, preempt_disable는 인터럽트 컨텍스트 간의 동기화에 아무런 역할을 하지 못하며 semaphore는 휴면 가능하므로 인터럽트에서는 아예 사용이 불가능하다.



4. [SMP System] 프로세스 컨텍스트 간의 동기화


spin_lock

프로세스 컨텍스트가 하나의 프로세서에서 유사 동시성을 가짐과 동시에 다수의 프로세서에서 진정한 동시성을 가지게 된다. CS가 다수의 프로세서에 의해 공유 되므로 spin_lock을 사용해야 다수의 프로세서 간에 동기화가 달성 된다.


preempt_disable

preempt_disable 은 특정 프로세서에서의 선점을 금지 한다. 예를 들어 A, B 두 개의 프로세서가 있다. 그리고 CS를  공유하는 1, 2, 3, 4 네 개의 태스크가 있다. 어떠한 원인인지는 몰라도(로드 밸런싱을 포함한 다수의 경우가 있을 수 있음) 태스크 1, 2는 A 프로세서에서 실행되고 있고, 태스크 3, 4는 B 프로세서에서 실행 된다고 가정한다. 프로세서 A의 태스크 1, 2 든 프로세서 B의 태스크 3, 4든 CS 진입 시에 preempt_disable을 호출하면 프로세서 A의 태스크 1, 2 간의 유사 동시성에 의한 동기화가 달성되고 프로세서 B의 태스크 3, 4 간의 유사 동시성에 의한 동기화도 달성 될 것이다. 하지만 이것만으로는 프로세서 간의 진정한 동시성에 의한 동기화는 달성할 수 없으므로 태스크(1, 2)와 (3, 4)간의 동기화는 spin_lock으로 달성 될 것이다.


preempt_disable은 유사 동시성에서의 동기화를 위해서만 사용되는 것이다.

SMP에서 프로세서 컨텍스트 간의 완벽한 동기화를 위해서는 다음과 같은 코드 모양이 될 것이다.


preempt_disable     --> 유사 동시성 동기화

spin_lock               --> 진정한 동시성 동기화

   .....

   CS

   .....

spin_unlock

preempt_enable


이렇게 코드가 작성 된다면 SMP에서 UP로 갈 경우 spin_lock만 걷어내면 될 것이다.



5. [SMP System] 프로세스 컨텍스트와 인터럽트 컨텍스트 간의 동기화


local_irq_disable + spin_lock

local_irq_disable은 로컨 프로세서의 모든 인터럽트를 금지 하므로 유사 동시성에서의 프로세스 컨텍스트 간의 동기화를 달성함과 동시에 프로세스 컨텍스트와 인터럽트 컨텍스트 간의 동기화를 달성할 수 있다. 하지만 인터럽트는 다른 프로세서에 의해 핸들링 될 수 있으므로 반드시 spin_lock을 더해줘야 한다. 이 조합을 하나의 함수로 처리한 것이 spin_lock_irqsave(), spin_lock_irqstore()이다. UP에서와 마찬가지로 유사 동시성에서의 데드락을 방지하기 위해 반드시 인터럽트를 먼저 금지하고 락을 잡아야 한다.


물론 preempt_disalbe을 사용해 프로세스 컨텍스트 간의 동기화를 해결할 수 있겠지만, local_irq_disable이 이를 해결해주므로 사용할 필요가 없다. 또한 semaphore는 휴면 가능하므로 인터럽트 컨텍스트에서는 아예 사용이 불가능하다.


preempt_disable     --> 프로세스 컨텍스트 간의 동기화 (유사 동시성) => 불필요

locak_irq_disable   --> 프로세스 컨텍스트 간의 동기화 + 프로세스 컨텍스트와 인터럽트 컨텍스트 간 동기화(유사 동시성)

spin_lock              --> 진정한 동시성 동기화

   .....

   CS

   .....

spin_unlock

local_irq_enable

preempt_enable



6. [SMP System] 인터럽트 컨텍스트 간의 동기화


local_irq_disable + spinlock

locak_irq_disable은 유사 동시성에서의 동기화를 위해 사용하는 것이며 (단일 프로세서에서의 인터럽트 컨텍스트 간의 동기화), 진정한 동시성에서의 동기화는 spin_lock을 통해 달성 된다. 또한 유사 동시성에서의 데드락을 방지하기 위해 반드시 인터럽트를 먼저 금지하고 락을 잡아야 한다. semaphore, preempt_disable는 인터럽트 컨텍스트 간의 동기화에 아무런 영할을 하지 못하며, semaphore는 휴면 가능하므로 인터럽트 컨텍스트에서는 아예 사용할 수 없다.



spin_lock

spin_lock은 두 개 이상의 프로세서가 실제로 동일한 시간에 같은 CS 구간에 접근할 때만 사용을 한다. 하나의 프로세서만을 사용하는 시스템에서는 시분할에 의한 유사 동시성만을 가지므로 spin_lock이 필요 없다. SMP 시스템에서는 두 개  이상의 프로세서에 의한 진정한  동시성과 하나의 프로세서에 의한 유사 동시성을 가진다. 즉, SMP 시스템에서는 두가지 종류의 동시성을 모드 가지는 것이다. 이때 spin_lock이 의미가 있는 경우는 두 개 이상의 프로세서에 의한 진정한 동시성을 가질때 이다. 그러므로 spin_lock을 생각할 때 SMP냐 UP냐, 선점이냐 비선점이냐를 생각하며 고민할 필요가 없다.



출 처 : http://blog.naver.com/redcultuer?Redirect=Log&logNo=130109621698








그간 SOCK_PACKET은 sniffer (tcpdump...)에서 패킷 빼올때나 쓰는것줄 알았는데 패킷을 보낼 때도 쓰더라..
packet socket도 raw socket과 비슷하게 application 단에서 패킷을 비교적 자유롭게 보내기 위해 사용되는데... - 내가 봤던 코드는 GARP를 전송하는 코드였뜸 -
문득 raw 와 packet socket의 차이점에 대해 궁금해 졌다.

차이점은 아래와 같다.
http://www.developerweb.net/forum/showthread.php?t=4981
Raw socket
1. Layer3까지 조작이 가능하다.
2. 일반적인 network stack을 이용한다.
3. 커널이 처리하기 전에 먼저 빼올 수 있다.
4. sockaddr_in을 사용한다.

=>raw socket도 hooking이 가능해야 한다는 말이다!

Packet socket
1. Layer2까지 조작이 가능하다.
2. network stack을 skip하고 device driver로 전송된다.
3. 커널이 처리하기 전에 먼저 빼올 수 있다.
4. sockaddr_ll을 사용한다.

=>hooking이 안된단 말이다!

큰 차이점을 요약하면
어느 layer까지 조작이 가능한가와 일반적인 network stack을 통과하느냐 그렇지 않느냐의 차이겠다. 

나에게 있어 header 조작이야 그냥 그렇고(지겨움 ^^;) network stack skip에 대한 부분은 매우 흥미로웠다.
만약 packet socket이 정말로 device driver (e1000..) 단으로 빠져 버린다면 net-filter에서 어떤 처리 (NAT, FW..)도 할 수 없다는 결론이 나온다.
어찌 관심을 안가질 수 있으리오..?

포스팅은 포스팅일 뿐이므로, - 이건 100% 신뢰 할 수 없다는 얘기다! - 
정말 그런지는 kernel source를 확인하는게 언제나 진리다 ^^;

이에 앞서 raw와 socket에 얽힌 이야기를 먼저 해보자.
- 위 원문에 RobSeace 씨가 한 얘기다 이분 왠지 포스 있다 -

Raw socket은 거의 BSD 표준을 따랐으며 유닉스 계열의 시스템에서 사용된다.
그 목적은 IP위에 올라갈 수 있는 사용자 단의 protocol을 쉽게 설계하도록 하는 거였지만,
몇몇 사람만 이렇게 쓰는것 같다.
<<< 넉두리 시작
 - 사실 누가 열라 시간을 들여가며 IP 바로 윗단의 (이말은 TCP, UDP, ICMP 등등을 사용하지 않는 다는거죠~) Layer를 만들 겠수? 만든다고 해도 kernel단의 network stack에 통합하지 복잡하게 user space에 만들지는 안을거유 (이말은 와닿지 않는다) -
>>> 넉두리 끝
요세는 ICMP 메시지를 주고 받는데 주로 사용되는것 같다. (맞는 말이죠??)

Packet socket은 Linux 독자적인 특성으로 다른 시스템에는 없다. 
하지만 각 시스템들은 표준에 동의하지 않았기 때문에 비슷한 역할을 수행하는 some을 가지고 있다. - 이게 여러분이 libpcap과 같은 higher-level library를 사용하는 이유다 -
어쨋든, 주된 차이점은 packet socket이 network-layer 보다는 link-layer에서 수행되는게 맞다.
때문에 여러분은 IP 트래픽 외에도 모든 종류의 트래픽을 sniffing 할수 있다.

- 이상 조사 끝, 코드 분석 시작 (아 근데 RobSeace 너무 스마트해 보여서 부럽다. 투덜대는거 빼고) -

자 그럼 packet이 정말 network stack을 skip하는 지에 대해 알아보자. 우훗우훗

가정:
packet socket의 경우 network stack을 skip 하므로 
sendto api 호출 시 초기 단계에서 dev_queue_xmit 혹은 hard_start_xmit을 call 할 것이다.

상콤하게 sock_sendmsg부터 가자

1. sock_sendmsg
필요한 것만 보자.
__sock_sendmsg에서 sock->ops->sendmsg를 call 한다.
역시나 virtual function~ 아 귀차나~~
af_packet.c를 뒤져보자!!
후훗 차자뜸

2. packet_sendmsg
등록은 packet_create 가 한다. 
sock->ops = &packet_ops; 

오!!!!! 굳굳 일단 가설은 적중 lol 
함수 마지막 부분을 보면 

     /*
     *    Now send it
     */

    err = dev_queue_xmit(skb);
    if (err > 0 && (err = net_xmit_errno(err)) != 0)
        goto out_unlock;

    dev_put(dev);

    return(len);

명확하다!! 난 이런게 좋다 ^_^
dev_queue_xmit -> hard_start_xmit -> e1000_xmit_frame (intel)

엄밀히 말하면 device driver로 곧바로는 아니지만 (dev_queue_xmit에서 queuing 처리를 하므로)
이정도는 애교로 봐줄 만 하다.
이는 또한 sock_packet이 hooking이 되지 않는 이유도 명확히 설명된다.

참고로 이 function을 보면 routing 역시 skip 하는걸 볼 수 있다.
dev = dev_get_by_index(ifindex); // output device를 얻어오고
...
skb->dev = dev; // 그대로 집어 넣는다.

이말은 application에서 반드시 해당 정보들을 설정해 주어야 한다는 것이다.

[출처] SOCK_RAW verse SOCK_PACKET|작성자 데비



출 처 : http://blog.naver.com/realbright1?Redirect=Log&logNo=94508080

1. AHCI 모드 사용하기

 - bios 설정 및 최신 인텔 드라이버 설치


2. 불 필요한 서비스 끄기
 - Superfetch
 - Windows Search (WSearch)

 - Windows Error Reporting Service


3. 자동 조각모음 예약 시스템 끄기 (디스크 조각모음)

 - 시작 -> 실행 -> dfrgui 입력 후 엔터 -> 일정 구성 -> 예약 실행(권장) -> 체크 해제


4. 디스크 속성 변경

 - "이 드라이브의 파일 속성 및 내용 색인 허용" 해제


5. 복원 기능 끄기


6. 가상 메모리 설정

 - 가상 메모리 영역을 다른 하드디스크 드라이버 영역으로 변경함


7 . 시스템 로그에 이벤트 기록 비활성화

  - 고급 시스템 설정 -> 시작 및 복구 -> 설정 -> 시스템 오류 -> 시스템 로그에 이벤트 기록 -> 체크 해제

  - 디버깅 정보 쓰기 -> 없음


8. 최대절전모드 끄기

 - powercfg -h off


9. 인터넷 익스플로어 임시 파일 용량 최소화

 

10. 전원 관리에서 고성능으로 설정.. 고급 설정에서 하드디스크 절전 사용안함


11. TRIM 동작 확인

 - fsutil behavior query DisableDeleteNotify 입력 후 엔터 -> "DisableDeleteNotify =  0" 이면 Trim 작동중이며

미작동시에는  fsutil behavior set DisableDeleteNotify 0 입력




hexedit 사용법

  /   -> search

 F9   ->블록지정

 F7  ->블록복사

 F11 ->복사된 내용을 파일로 저장



[출처] 포렌식 4|작성자 미키


Canonical

터미널 입력은 새줄문자('\n'), EOF, 또는 EOL 문자들로 종료되는 한 라인으로 처리 된다. 어떤 입력도 사용자에 의해 한 라인 전체의 입력이 종료되기 전에 읽혀질 수 없고, read 함수는 얼마나 많은 바이트가 요청되었는지에 상관없이, 많아야 오직 한 줄의 입력을 반환할 뿐이다.

NonCanonical

문자들은 라인들로 묶여지지 않고, ERASE와 KILL 프로세싱은 수행되지 않는다. 비정규입력에서(NonCanonical) 읽혀진 바이트들은 MIN과 TIME을 설정함으로 인해서 제어 된다.

MIN -> 읽어 들은 문자 갯수

TIME -> MIN에서 읽어 들인 문자 갯수가 충족되지 않을시 설정한 시간에 OUT



int tcgetattr(int fd, struct termios *p)

파일기술자와 연관된 터이널 디바이스의 속성을 시험하는데 사용된다. 그 속성은 구조체 p가 가리키는 곳으로 반환된다.


int tcsetattr(int fd, int when, const struct  termios *p)

파일기술자와 연관된 터미널 디바이스의 속성을 설정한다. 새로운 속성들은 구조체  p가 가리키고 있는 곳으로부터 가져온다. when 인수는 이미 큐된(큐에 저장되어 있는) 입력과 출력을 어떻게 취급할 것인지를 정하는 것으로 다음 값들 중 하나를 사용할 수 있다.

TCSANOW

즉시 속성을 변경시켜라.

TCSADRAIN

큐에 저장된 출력이 쓰여질 때까지 기다린 후에 속성을 변경하라. 당신은 변경하는 파라미터가 출력에 영향을 미칠 때 이 옵션을 사용한다.

TCSAFLUSH

이것은 TCSADRAIN과 같지만, 큐에 저장된 입력을 버린다.

TCASASOFT

위에 있는 어떤 것과도 덧붙여 사용할 수 있는 플래그 비트이다. 이것은 하드웨어에 대한 상황의 변경을 금지하기 위한 것이다. 이것은 BSD 확장이다. BSD가 아닌 시스템에서는 아무런 영향을 받지 않는다.



O_NOTTY : open 하려는 process에 대해 device를 controlling terminal로 할당하지 말라는 것이다.

controlling terminal : process가 foreground이며, device가 현재 terminal을 제어함을 의미



/////////////////////////////////////////////////////////////////////////////////////////////////////////////////


c_cc에서 사용가능한 매크로

정규모드(canonical)에서 배열의 인덱스

 

-VEOF : EOF 문자

-VEOL : EOL 문자

-VERASE : ERASE 문자

-VINTR : INTR 문자

-VKILL : KILL 문자

-VQUIT : QUIT 문자

-VSUSP : SUSP 문자

-VSTART : START 문자

-VSTOP : STOP 문자

 

비정규 모드(non-canonical)에서 배열의 인덱스는 다음과 같다

-VINTR : INTR 문자

-VMIN : MIN 문자

-VQUIT : SUSP 문자

-VTIME : TIME 값

-VSTART : START 문자

-VSTOP : STOP 문자

특수 문자와 비정규 모드에서의 MIN과 TIME은 입력 문자를 발전적으로 처리하는데 있어서 매우 중요하다.

 

TIME 과 MIN 값 - 비정규 모드에서 사용되고, 입력으로 부터 읽어들이기를 제어 하는데 함께 사용된다. 프로그램이 터미널과 연관된 파일 기술자로 부터 읽기를 시도할때 일어나는 사건을 제어한다.

-MIN=0이고 TIME=0 : read는 항상 즉시 리턴한다.

-MIN=0이고 TIME>0 : read는 읽어들일 문자가 있거나, TIME/10초가 경과했을 때 리턴한다.

-MIN>0이고 TIME=0 : read는 MIN개의 문자를 읽을 때까지 기다릴 것이고, 읽어들인 문자의 개수를 리턴할 것이다. 파일의 끝이라면 0을 리턴한다.

-MIN>0이고 TIME>0 : read가 호출 되었을때 읽어들일 문자를 기다린다. 첫 번째 문자가 도착하면이제 타이머가 작동한다. read는 MIN개의 문자를 읽어들였거나 타이머가 TIME/10초 만큼 경과했을 때에 리턴할 것이다.


출 처 : http://hano1030.springnote.com/pages/2748626.xhtml







리눅스 커널 스택에 대해서 궁금합니다.

1.커널 스택은 프로세스마다 하나씩 생성되는 건가요 ?
2.커널 스택에는 어떤 정보가 들어가게 되나요 ? (얼핏 알기로는 해당 프로세스에 인터럽트가 걸리면 이에 필요한 정보들을 커널 스택에 저장해 놓고 사용한다고 하던데요...)
3.프로세스 하나는 4기가의 가상 공간을 사용한다고 들었습니다. 이 중에서 0~3기가 까지는 응용프로그램에서 사용하는 공간이고 3~4기가는 커널이 사용하는 공간이라고 알고 있는데요...
여기서 3~4기가 공간과 커널 스택이 어떠한 연관 관계가 있나요?

고수님들의 답변 부탁드립니다.

----------------------------------------------------------------------------------------------------------------------------------------


1. 커널 스택은 프로세스마다 하나씩 생성됩니다.
일반적인 프로세스는 User Mode 스택과 Kernel Mode 스택을 각각 하나씩 가지고 있습니다.
User Mode에서 Kernel Mode로의 전환은 시스템호출이나 인터럽트가 발생하면 일어납니다.
즉, esp 레지스터는 프로세스가 User Mode이면 User Mode 스택의 top을 가르키다가
Kernel Mode로 전환이 되면 Kernel Mode 스택의 top을 가르킵니다.

2. Kernel Mode 스택은 적어도 다음 두가지 목적으로 사용됩니다. 다른 사용처는 딱히 생각나지 않네요.
가. Kernel Mode로 전환된 프로세스는 언젠간 다시 User Mode로 되돌아가야 합니다.
따라서 User Mode로 전환하기위해 필요한 정보 중 일부를 저장합니다. (일부는 다른 곳에 저장합니다.)
나. Kernel Mode에서 함수를 호출하게 되면 그 함수의 지역변수는 Kernel Mode 스택에서 할당됩니다. (User Mode에서 함수를 호출하면 지역변수가 User Mode 스택에 할당되는 것과 같습니다.)
참고로 80x86 아키텍처에서 커널 스택으로 할당된 공간의 크기는 8KB로 고정되어있습니다. 프로세스 생성때 한번 할당되어 작아지지도 커지지도 않습니다. 따라서 커널에 있는 함수에서는 지역변수를 많이 할당하거나 재귀 함수 호출을 하면 좋지 않습니다.

3. 어떻게 설명드려야할 지 상당히 난해한 질문이군요.
커널은 주소 공간 3~4GB를 사용합니다. Kernel Mode 스택은 Kernel Mode에서만 사용되므로 커널 주소 공간에서 할당됩니다.
즉, User Mode 스택을 가르키는 esp 값을 읽어보면 0GB~3GB 사이의 값을 가지고 Kernel Mode 스택을 가르키는 esp 값을 읽어보면 3~4GB 사이의 값을 가지게 됩니다.

4. 기타

가. 프로세스의 User Address Space는 프로세스마다 각각 다르지만, Kernel Address Space는 모든 프로세스가 동일하게 봅니다. 즉, 프로세스 A와 프로세스 B의 특정 가상주소 (예를 들면 0xa0001000) 은 서로 다른 물리주소로 맵핑될 수 있습니다. 하지만 특정 커널 공간 주소 (예를 들면 0xc0001000) 는 모든 프로세스에서 동일한 물리주소로 맵핑됩니다.
이를 위해서 커널은 kernel master page table (swapper_pg_dir 변수가 가르킴)을 관리하고, 필요할 때마다 특정 엔트리를 kernel master page table에서 해당 프로세스의 page table에 복사를 합니다 -- 이런 작업은 Kernel Mode에서 페이지 폴트가 발생했을 때 페이지 폴트 핸들러가 수행합니다.

나. 시스템호출, 인터럽트 핸들러, 커널 모듈 등은 임의의 프로세스의 context를 이용합니다. 예를 들어, 프로세스 A가 User Mode에서 수행되고 있을 때 timer interrupt가 발생하는 경우 Kernel Mode로 전환하여 timer interrupt service routine을 수행하게 되는데 이때 프로세스 A의 page table과 Kernel Mode 스택을 빌어 쓰게됩니다.
Timer interrupt와 프로세스 A와는 별다른 연관이 없지만 interrupt 발생시점에 프로세스 A가 CPU를 점유하고 있었기 때문에 부하가 큰 context switch 등을 따로 하지 않고 프로세스 A의 context를 그대로 이용하는 것입니다. 다만 커널 모듈 등이 기능의 일부를 따로 커널 쓰레드를 생성하여 구현한 경우라면 그 커널 쓰레드의 context를 사용하겠죠.

출 처 : http://kldp.org/node/73308

커널 2.6.36에서는 file_operations 에서 ioctl 이 제거되었고
대신에 unlocked_ioctl 과 compat_ioctl 이 사용되게 되었다.

unlocked_ioctl 과 compat_ioctl 은 2.6.11 에서 처음 추가되었는데 그 이유는 BKL 이슈에 대한 것때문이다.
BKL 은 Big Kernel Lock 의 약자인데 커널에서 락을 이용하지 않게 하려는 시도가 꾸준히 있어왔다.

그 이유는 커널에서 특히 SMP 구조에서 락에 들어가는 비용이 너무 많기 때문이며, 효율적으로 사용하기 위해서다.
그런 이유로 도입된 것이 RCU(read copy update) 이다.

어쨋든 ioctl 이 호출되면 커널 락이 수행되고 자동적으로 SMP 구조에서는 비효율을 가져오고 있었다.
그래서 사용되는 것이 unlocked_ioctl 이다.

쉽게 얘기해서 모든 CPU에 대해서 lock 을 걸던것을 개별적인 lock 을 걸수 있게끔 바꾼것이다.

간단히 어떻게 해야 하는지 확인하자.

static int extio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int param_size;
unsigned int value;

if(_IOC_TYPE(cmd) != IOCTL_FN_ALARM) return -EINVAL;
if(_IOC_NR(cmd) >= ALARM_FN_MAXNR) return -EINVAL;

param_size = _IOC_SIZE(cmd);
if(param_size) {
if(_IOC_DIR(cmd) & _IOC_READ) {
if (unlikely(!access_ok(VERIFY_WRITE, (void *)arg, param_size)))
return -EFAULT;
}
if(_IOC_DIR(cmd) & _IOC_WRITE) {
if (unlikely(!access_ok(VERIFY_READ, (void *)arg, param_size)))
return -EFAULT;
}
}

switch (cmd)
{
caseFN_IOCTL_GET:
{
copy_to_user((unsigned int *)arg, &value, sizeof(unsigned int));
return 0;
}
caseFN_IOCTL_PUT:
{
copy_from_user(&value, (unsigned int *)arg, sizeof(unsigned int));
return 0;
}
}

return -ENOTTY;
}

이것이 전통적인 방식의 ioctl 이다.
이제는 여기서 이렇게 바꾸어야 한다.
static DEFINE_MUTEX(extio_mutex);
static int extio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int param_size;
unsigned int value;

if(_IOC_TYPE(cmd) != IOCTL_FN_ALARM) return -EINVAL;
if(_IOC_NR(cmd) >= ALARM_FN_MAXNR) return -EINVAL;

param_size = _IOC_SIZE(cmd);
if(param_size) {
if(_IOC_DIR(cmd) & _IOC_READ) {
if (unlikely(!access_ok(VERIFY_WRITE, (void *)arg, param_size)))
return -EFAULT;
}
if(_IOC_DIR(cmd) & _IOC_WRITE) {
if (unlikely(!access_ok(VERIFY_READ, (void *)arg, param_size)))
return -EFAULT;
}
}

mutex_lock(&extio_mutex)
switch (cmd)
{
caseFN_IOCTL_GET:
{
copy_to_user((unsigned int *)arg, &value, sizeof(unsigned int));
mutex_unlock(&extio_mutex);
return 0;
}
caseFN_IOCTL_PUT:
{
copy_from_user(&value, (unsigned int *)arg, sizeof(unsigned int));
mutex_unlock(&extio_mutex);
return 0;
}
}

mutel_unlock(&extio_lock);
return -ENOTTY;
}
세가지가 추가되었다.
static DEFINE_MUTEX(extio_mutex);
mutex_lock(&extio_mutex);
mutex_unlock(&extio_mutex);

이제 동일한 ioctl 에 접근하는게 아니라면 SMP 구조에서도 mutex 로 보호되는 상태만 아니면 
동시에 ioctl 에 접근할수 있게 되었다.
또 하나 있는게 compat_ioctl 인데 이것은 32bit 와 64bit 간의 호환성을 갖도록 설계된 ioctl 이다.
자세한 것은 다음에 다시 설명하도록 합니다.

출처 :  http://forum.falinux.com/zbxe/?document_srl=553645

+ Recent posts