팁이라기 보다는 문제 제기에 가깝습니다. ==================== 출처 http://phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=62537&page=1 http://www.phpschool.com/gnuboard4/bbs/board.php?bo_table=tipntech&wr_id=62631&page=1
리눅스에서 wget의 용도는 참 다양합니다.
다른 홈페이지의 뭔가를 가져오고(때로는 긁어오고...) 제 경우는 내부에서 php를 실행할때로 자주 사용합니다.
근데 man wget 하고 여러 옵션을 구경하다가
-r
--recursive
라는 놈이 있어서 한번 실행을 해봤습니다.
아예 홈페이지의 내용을 디렉토리채 긁어오는군요.
테스트해보시려면
wget http://www.phpschool.com -r 해보십시요.
www.php.school.com 이라는 폴더가 하나 생기고 그 하위 폴더들이 주루룩 나오는군요.
디렉토리 스트럭처가 적나라하게 보입니다.
banner community guild index.html survey
biznbaza company html_sub index.php title_image
class gnuboard4 images menu_images ttrend
물론 php 소스가 아니고 출력된 html의 형태로 저장되기는 하지만 기타 css, js, 이미지등등은 그대로 가져오는군요.
저만 모르고 있었던 것인가요?
뒷북이라면 죄송합니다만....
여기서 하나...
남의 홈페이지 긁어오는 데는 그만이지만
반대로 누군가 내 홈페이지를 긁어가는 것은 기분이 엄청 나쁠 것같습니다.
해서~~
아무리 생각해봐도 wget을 막기는 막아야할 것같습니다만..
이놈이
-U agent-string
--user-agent=agent-string
옵션까지 무장을 하고 있어서 agent로 차단하는 것은 불가능해보입니다.
혹씨나해서 살펴보니 robots.txt가 먹히는군요.
User-agent:*
Disallow:/
하니까 못 긁어가네요.
더좋은 방법이 있는지 모르겠습니만...
참고하시기를...
Linux&Unix
- [펌] wget을 이용한 웹 긁어오기 2011.01.21
- 크리티컬 섹션, 뮤텍스, 세마포어 2011.01.19
- 리눅스 utf-8 캐랙터셋 변경 2011.01.11
- find 명령어 2011.01.11
- 리다이렉션과 파이프 2011.01.06
- 리눅스 프롬프트 설정 2010.12.15
- Kernel Timer 2010.12.14
- 리눅스 인터럽트 2010.12.09
- ioctl() 디바이스 제어 2010.12.03
- Debian apt-get 공개키 에러 발생시... 2010.11.18
[펌] wget을 이용한 웹 긁어오기
크리티컬 섹션, 뮤텍스, 세마포어
관련된 이론 분야 : 운영체제론 크리티컬 섹션(임계구역) / 뮤텍스(상호배제) / 세마포어 이것들은 한양대 컴공과 3학년 1학기 과정에 있었던 운영체제론의 핵심적인 내용이었습니다. 허신 교수님의 운영체제론 수업을 들었었는데 이론의 맥을 잘 짚어주셨던 기억이 나네요. 열심히(?) 공부해서 시험도 보고 성적도 좋았지만 막상 그 개념들을 실제로 적용해볼 기회가 없으니 개념이 좀 두리뭉실해서 한 번 정리해 보았습니다. 제가 이해한 내용을 복습하기 위해 정리한 것이라서 틀릴 수도 있으니 많은 성원 바랍니다 (뭔 소리야 ㅋㅋ) 모두 동기화 오브젝트에 관련된 이론인데... 이 이야기를 할 때면 어김없이 나오는게 호프집 화장실에서 똥싸는 이야기더군요 - _ -;; 오늘의 수업은 이름하여... 미쉘린의 호프집 화장실 이론 1. 크리티컬 섹션 (임계구역), Critical Section 호프집에 화장실이 있습니다. 이 화장실에는 변기가 하나밖에 없습니다. 그래서 한 번에 한 사람씩 들어가야 되지욤... (화장실 안에 서서 기다리면서 누가 똥싸고 오줌싸는걸 지켜볼 수는 없는 노릇) 이 변기가 크리티컬 섹션입니다. 프로그래밍할 때에는 주로 CS (Critical Section)라고 언급됩니다. MFC 에는 크리티컬 섹션에 대한 클래스가 정의되어 있어서 다음과 같이 사용할 수 있습니다. CCriticalSection RestRoom; RestRoom.Lock(); 용변보기 RestRoom.Unlock(); Lock() 과 Unlock() 사이의 구간이 크리티컬 섹션입니다. 스레드에서 이렇게 정의한 부분은 한 번에 하나의 스레드만 접근할 수 있습니다. (스레드에 대한 이야기는 제 지난 컴퓨터 이론 포스트를 참고하시기를...) 호프집에 동수, 일구, 빠박이가 있습니다. 셋이서 신나게 술을 마십니다. 어느순간 세사람 모두 오줌이 마렵습니다. 동수일행 프로세스 CCriticalSection RestRoom; // 전역변수 동수 스레드 { 일구, 빠박이랑 술마시기 if ( 오줌마렵다 ) { RestRoom.Lock(); 용변보기 RestRoom.Unlock(); } } 일구 스레드 { 동수, 빠박이랑 술마시기 if ( 오줌마렵다 ) { RestRoom.Lock(); 용변보기 RestRoom.Unlock(); } } 빠박이 스레드 { 동수, 일구랑 술마시기 if ( 오줌마렵다 ) RestRoom.Lock(); 용변보기 RestRoom.Unlock(); } } 지난 포스트에 하나의 주 프로세스가 여러 개의 스레드를 생성하여 CPU 상에서 여러 개의 스레드가 돌아간다는 이야기를 했습니다. 동수, 일구, 빠박이는 모두 각각의 독립적인 스레드입니다. 프로그램이 종료할 때까지 (호프집에서 나갈 때까지) 항상 CPU 상에서 돌아가고 있지요. 술마시다가 어느순간 세 사람 모두 오줌이 마렵습니다. 동수가 먼저 화장실로 냅다 달립니다. 동수 : 일구야 ~ 형 먼저 갈께 ㅜ0ㅜ 일구 : 아 ㅅㅂ~~~ 빠박이 : 가지마 ~~~~~ 동수가 먼저 가서 용변을 봅니다. 화장실은 한 사람 밖에 들어갈 수 없기 때문에 동수가 화장실에 들어가는 순간 RestRoom.Lock() 이 됩니다. RestRoom.Lock() 걸리면 다른 스레드는 RestRoom.Lock() 구간에 서서 Unlock() 이 될 때까지 무작정 기다립니다. ... 일구랑 빠박이는 화장실 문앞에 서서 기다립니다. 동수가 용변보고 나오면 RestRoom.Unlock() 이 됩니다. 그럼 이제 일구랑 빠박이중 누군가 먼저 들어간 사람이 RestRoom.Lock() 을 다시 호출하겠지요. 요 화장실 RestRoom Lock() ~ Unlock() 구간이 바로 CS ..... 크리티컬 섹션 입니다. 2. 뮤텍스, Mutex 뮤텍스의 용도는 기본적으로 CS 와 같습니다. 간단하게... 어렵지 않게... 헷갈리지 않게... 차이점만 짚어봅시다. CS 는 단일 프로세스의 스레드에 대해서만 동작합니다. 반면에, 뮤텍스는 여러 프로세스의 스레드에 대해서도 동작합니다. 동수 일행이 호프집에 들어오는 순간 3 개의 스레드가 생성됩니다. (동수 / 일구 / 빠박이 스레드) 엇 ?? 근데 또 다른 일행이 호프집에 들어왔습니다. 봉팔 일행입니다. (봉팔 / 상팔 / 영팔 ) - 이름만 다를 뿐 동수 일행과 똑같은 프로세스 입니다. (메모리상에 똑같은 프로그램의 프로세스 2 개가 올라왔다고 생각하면 됩니다. 두 번 실행됐다는 말) 얘들이 들어오면서 또 3 개의 스레드가 생성됩니다. 메모리상에는 6 개의 스레드가 돌아가고 있습니다. 이제... ( 동수 / 일구 / 빠박이 ) // ( 봉팔 / 상팔 / 영팔 ) 각각의 스레드가 동시에 화장실에 가지 못하도록 해야 합니다. 이 때, 뮤텍스를 사용합니다. CS 를 사용하게 되면 중복된 리소스 점유가 발생할 수 있기 때문입니다. 위 코드를 보면 RestRoom 은 동수 일행 프로세스의 전역 변수로 선언되어 있습니다. 그래서 동수 일행끼리는 "동수가 화장실에 갔으니까 일구랑 빠박이는 화장실에 갈 수 없다" 는 사실을 전역변수 CCriticalSection RestRoom 을 통해 명시적으로 알 수 있습니다. 하지만 봉팔 일행은 동수 일행의 RestRoom 과는 또다른 그들만의 RestRoom 을 가지고 있으므로 동수 일행중 누군가가 화장실에 있는지 여부는 판단할 수 없습니다. 그래서... "지금 화장실에 아무도 없으니까 누구든지 가도 된다" 는 결정을 내립니다. 봉팔이가 화장실로 달려가는 순간 화장실 문이 열리고 동수가 용변보는 모습을 발견합니다 !! 봉팔 : (엇.......!! 아무도 없는줄 알았는데 누가 있잖아 !!) 결국 봉팔이는 용변을 못 보고 예기치못한 사태에 멈춰 서 있게 됩니다. (실제로 이런식으로 프로그래밍을 하면 런타임 오류가 나지 않을까 생각되네요... 실제로 안해봐서 생각만...;;) 3. 세마포어, Semaphore 복잡하니 쉽게 갑시다... 세마포어는 CS, 뮤텍스가 가지는 특징에 하나를 더 가집니다. 세마포어는 특정 영역의 코드를 실행하는 스레드의 최대 개수를 설정할 수 있습니다. 지금은 1인용 화장실을 언급하였지만... 만약 호프집에서 화장실을 증축하여... 4인용 화장실이 되었다면... 이제 4명까지 화장실에 들어갈 수 있습니다. 이런 카운터를 세마포어로 구현할 수 있고 4인용 화장실 CSemaphore semaphore(0, 4); 첫번째 매개변수 : 리소스 카운터의 초기값 두번째 매개변수 : 리소스 카운터의 최대값 다시 돌아가서... 1인용 화징실에 열쇠라는 개념을 도입하여... 1인용 화장실 CSemaphore key(0, 1); 이런식으로도 활용이 가능합니다. 음... 여기에 또 문제가 생기는데 만약 누군가 1인용 화장실의 열쇠(세마포어)를 가지고 도망가버리면 아무도 화장실에 들어갈 수 없는 문제가 생깁니다. 이건 데드락이라고 하는건데... 오늘은 여기까지 ! 다음 기회에 ~~~~~~~~~ p.s : 제 생각을 정리한 내용이니 틀린 내용이 있을 수 있습니다 ;;;;;; 출 처 : http://blog.naver.com/thx4alice?Redirect=Log&logNo=110022369987 [출처] 크리티컬 섹션, 뮤텍스, 세마포어|작성자 미쉘린
리눅스 utf-8 캐랙터셋 변경
UTF-8 캐릭터셋으로 변경하기위한 방법은 여러가지 작업을 거쳐야하는 까다로운 작업이다. #!/bin/bash
새로운 사이트를 구축하는데는 별다른 어려움이 없지만
기존사이트를 이전하기 위해서는 알게 모르게 많은 수작업이
들어간다.
만일 HTML 파일내용을 EUC-KR에서 UTF-8로 변경해야 할
경우라면 다음과 같은 명령을 사용한다.
iconv -c -f euc-kr -t utf-8 a.html > a.html.utf8
iconv 명령은 여러개의 파일을 동시에 변환할 수 가 없다. 따라서
여러개의 파일 혹은 디렉토리상의 HTMl을 변경하고자 할때는
다음과 같이 크립트를 작성하여 변환을 해야 한다.
for DIR in `find . -type f `
do
echo "$DIR done............................"
iconv -c -f euc-kr -t utf-8 $DIR > aa
rm -f $DIR ; mv aa $DIR
done
iconv옵션중에 "-c"를 붙여주는 이유는 간혹 잘못입력된 한글 혹은
특수문자의 경우 UTF-8 변환이 되지 않는다. 이와같은 경우로
파일이 삭제되는 경우를 방지하기 위해 -c를 주면 변환할 수 없는
파일이 있더라도 강제로 변환하기 위함이다.
위처럼 파일의 내용을 변경했으면 meta 태그를 변경하는
과정이 필요하다. 아무리 실제 파일 내용이 UTF-8일지라도
이걸 표현하는 Explorer 나 Firefox에서는 태그가 제대로
표현되어 있지 않으면 UTF-8로 표현되지 못한다.
따라서 다음과 같은 명령으로 meta의 character-set을 변경해야
한다.
find . -name '*.html' -exec perl -pi -e 's/euc-kr/utf-8/g' {} \;
다음으로 간혹 개념없는 유저들이 올리는 한글이름으로 된
파일을 UTF-8파일명으로 변경해야 한다. iconv는 파일의
실제 내용을 utf-8로 변경했을뿐 파일명은 다른 문제라서
다음과 같은 명령으로 파일명을 변경해야 한다.
convmv -r -f euc-kr -t utf-8 --notest *
convmv의 경우 리눅스상의 기본 명령어가 아니므로 www.rpmfind.net 등에서 rpm을 검색하여 설치해야 한다.
주의사항 : UTF-8로 변경하는 작업은 생각만큼 쉬운 작업이
아니다. 지금 완전히 정착된 것도 아니고 해서 변환에 신중신중을
기해야 한다.
출처 : http://blog.naver.com/ssik425?Redirect=Log&logNo=10088230675
[출처] [UTF8] 리눅스 convmv를 이용한 UTF-8 캐릿터셋으로 변경|작성자 씩
find 명령어
사용형식 [찾을 디렉토리경로] [찾기옵션] [찾은후행할 작업] option [찾을 디렉토리경로] . : 현재 디렉토리 이하를 검색대상으로 한다. / : 루트디렉토리(파일시스템전체) 이하를 대상으로 한다. ~ID : 지정된 ID의 홈디렉토리이하를 대상으로한다. [찾기옵션] -empty : 비어있는 파일을 찾는다. -uid UID : 지정된 UID를 갖는 파일을 찾는다. -gid GID : 지정된 GID를 갖는 파일을 찾는다. -group 그룹명 : 지정된 group을 갖는 파일을 찾는다. -name : 지정된 형식의 패턴을 가지는 파일을 찾는다. -newer : 지정된 파일 이후에 생성된 파일을 찾는다. -perm : 지정된 퍼미션을 가진 파일을 찾는다. -used 일자수 : 최근 n일 이후에 변경된 파일을 찾는다. -user : 지정된 파일을 소유하고 있는 소유자의 모든 파일을 찾는다. [찾은후 수행할 작업] -print : 찾은 내용을 보여준다. -exec "수행명령어" : 검색된 파일을 대상으로 :수행명령어"를 실행한다. [예제] 특정 사용자의 ID 소유로된 모든 파일 찾기. [os] find / -user khi083 -print 현재 디렉토리 이하부터 test 파일명을 찾아 보여준다. [os] find . -name test -print khi083 사용자의 홈디렉토리에서 test 파일명을 찾아 보여준다. [os] find ~khi083 -name test -print 특정 파일을 찾은 후 자동 삭제방법. [os] find ~khi083 -name test -exec rm -f {} \; 지정한 소유자의 모든 파일을 찾아서 확인하기. [os] find / -user khi083 -exec ls -l {} \; 특정용량 이상되는 파일들 모두찾기. [os] find /usr/ -size +10000k -exec ls -l {} \; -- 약 10MB이상 특정 퍼미션을 가지고 있는 파일들을 모두 찾기 [os] find / -perm 4755 -exec ls -l {} \; 존재하는 모든 링크파일 찾기 [os] find / -type l -exec ls -l {} \; 디렉토리 이하에서 "doc" 라는 문자를 포함하고 있는 파일을 찾아서 파일의 위치와 파일명, 포함된 행을 출력한다. [os] find /etc type f -exec egrep -i "doc" /dev/null {} \; -------------------------------------- 보안 관련된 find -------------------------------------- 지정된 일자 이후에 변경된 모든 파일 찾기(서버점검시에 서버해킹으로 인하여 변경된 파일을 찾을 경우) [os] find / -used 2 -exec ls -l {} \; -- used 뒤에 나오는 숫자는 "일" 즉, 24시간 단위. 지정된 파일보다 이후에 생성된 파일 찾기(해킹된 파일이나 백도어 파일을 찾은 후에 그 파일과 함께 시스템에 생성된 파일찾기) [os] find / -newer /root/file1.txt -exec ls -l {}; -- used 뒤에 나오는 숫자는 "일" 즉, 24시간 단위. root소유의 SetUID 파일 찾기 [os] find / -user root -perm -4000 -print 서버내부에서 .bash_history 파일을 모두 찾아서 확인하기(root소유의 .bash_history파일이 용량이 0이라면 이는 매우 심각한 경우로서 거의 99%이상은 해킹되었다고 보셔도 무방하다.) [os] find / -name .bash_history -exec ls -l {} \; 소유자가 없는 파일 또는 소유그룹이 없는 무적파일 찾기 [os] find / -nouser -o -nogroup -print -- -o옵션은 "OR"를 의미한다 출 처 : http://blog.naver.com/nixblade?Redirect=Log&logNo=10092313804
리다이렉션과 파이프
리다이렉션과 파이프 시스템에 로그인하면, 쉘은 기본적으로 표준 입력장치로 키보드, 표준 출력장치로 모니터를 설정한다. 리눅스 시스템에서 리다이렉션과 파이프 - 입력과 출력의 방향을 변경할 수 있다. 리다이렉션 표준 출력의 리다이렉션 - 화면 출력을 파일 출력으로 바꾸는 것 - 리다이렉션을 의미하는 문자 è ‘>’ n ex) $ ls –al > test - 파일이 이미 존재하고 있더라도 해당 파일을 무조건 덮어 씌우므로.. n ex) $ ls –al >> test2 표준 입력의 리다이렉션 - 표준입력을 키보드에서 파일로 바꾸는 것 * sort 명령어 : 키보드로부터 입력된 데이터를 오름차순으로 정렬하여 그 결과를 표준 출력장치인 모니터 화면에 보여주는 명령어 - 표준 입력의 리다이렉션 è ‘<’ n ex) $ sort < names n ex) $ sort < names > sorted 파이프라인 파이프 - 어떤 명령의 실행결과를 다음 명령의 입력 값으로 만들기 위해 두 명령어를 같이 쓸 수 있게 해주는 것! - 파이프를 만들기 위해 두 명령어 사이에 | (vertical bar)를 놓아야 한다. n 표준 출력 | 표준 입력 파이프라인 분리 - Tee 파이프라인 분리 - 하나의 입력을 가지고 두 개의 동일한 출력을 가지는 명령어 - 일반적 형식 n tee filename n ex ) $ cat names | sort | tee sorted | pr 출처 : http://blog.naver.com/dbwls0105?Redirect=Log&logNo=30037806187 [출처] [study] 리다이렉션과 파이프|작성자 포이베
이렇게 입력하였을 때 명령이 실행된 결과가 test 파일에 저장
‘>>’ 을 사용하여 이미 존재하는 파일의 끝에 추가하여 쓰도록 한다.
$ cat test2
$ ls –al >> test2
$ cat test2
names 파일로부터 입력받아 그 결과를 표준출력장치인 화면에 출력
표준 입력과 표준 출력을 동시에..
두 명령어 사이에 | 가 놓이면, | 을 기준으로 왼쪽은 표준 출력 명령이 되고, 오른쪽은 표준 입력 명령이 된다.
cat 명령은 names 파일을 표준 출력하고, sort 명령은 cat에서 표준 출력된 데이터를 입력 값으로 받아 정렬한다. 정렬된 데이터를 다시 표준출력하며, more 명령은 sort에서 정렬된 데이터를 출력한다.
즉, 파이프에 tee를 위치시키면 입력 데이터에 대한 두 개의 동일한 출력을 만들어 낼 수 있다는 것!
파이프라인 tee를 이용해 데이터를 정렬하여 sorted라는 이름으로 저장하고 인쇄하는 예
리눅스 프롬프트 설정
리눅스 터미널을 열었는데
쉘 프롬프트 모양이
bash-3.1#
이런식으로 나와 있을 경우가 있습니다.
이런경우 현재 디렉토리 위치도 모를뿐더러 현재 user가 누군지도 모릅니다.
vi .bashrc 를 열어서
export PS1="[\u@\h \W]\$" 를 추가해줍니다.
source .bashrc를 통해 bashrc를 다시 읽습니다.
옵션)
참고)
Kernel Timer
커널 타이머 이용시
struct timer_list : 커널 타이머 구조체
init_timer(): 커널 타이머 구초제를 초기화 한다
add_timer(): 커널 타이머에 수행될 함수를 등록한다
del_timer(): 커널 타이머 목록에서 등록된 것을 제거한다.
커널 타이머는 동작 시간이 1/Hz 단위로 1/Hz초 이하의 호출 주기는 사용이 불가능 하다
다음은 커널 2.6 버젼에서의 타이머 동작이다.
struct time_list 변수는
1. unsigned long expires, 2 unsigned long data, void (*function)(unsigned long)을 일반적으로 지정하여 사용한다.
1. unsigned long expires 는 다음과 같이 초기화 한다
kerneltime.expires=get_jiffies_64()+(3*HZ/10);
(현재 jiffies값을 얻어서 0.03초가 지난후로 설정)
2. unsigned long data 는 timer 함수에 전달할 데이터를 참조하기 위한 주소를 리턴한다.
3. void (*function)(unsigned long)는 타이머 시간이 만료하고 수행할 함수이다.
init_timer는 timer 구조체를 초기화 한다. 앞에서 설명한 expires,data,function 필드를 초기화 한다.
add_timer는 커널 타이머에 호출될 timer_list 구조체를 등록한다.
del_timer는 커널 타이머를 제거한다. 일반적으로 커널 타이머가 등록되고 시간이 초과하여 커널 타이머에 등록된 함수가 호출되면 등록된 커널 타이머는 자동적으로 제거된다. 하지만 디바이스 드라이버는 등록된 커널 타이머가 확실하게 후출되어 제거될 것이라는 확신이 있더라도 모듈 형식으로 디바이스 드라이버를 작성할 경우 디바이스 드라이버의 종료 루틴에 del_timer() 함수를 호출하여 모듈이 제거 되었을때 제거된 번지에 속해 있던 함수가 호출되지 않도록 하여야 한다.
커널 타이머 예
1초마다 메시지를 출력한다
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/time.h>
#include <linux/timer.h>
#define TIME_STEP (1*HZ)
struct timer_list *timer;
static int timertick=0;
void kerneltimer_timeover(unsigned long arg ); <--Timerover 시 실행할 함수
void kerneltimer_registertimer(struct timer_list* ptimer, unsigned long timeover )
{
init_timer( ptimer );
ptimer->expires = get_jiffies_64() + timeover;
ptimer->data = NULL;
ptimer->function = kerneltimer_timeover ;
add_timer( ptimer);
}
void kerneltimer_timeover(unsigned long arg )
{
printk("I am timer tick:%d\n",timertick);
timertick++;
kerneltimer_registertimer( timer, TIME_STEP ); <--timerover 하면 재 등록
}
int kerneltimer_init(void)
{
timer= kmalloc( sizeof( struct timer_list ), GFP_KERNEL );
if( timer== NULL ) return -ENOMEM;
memset( timer, 0, sizeof( struct timer_list) );
kerneltimer_registertimer( timer,TIME_STEP );
return 0;
}
void kerneltimer_exit(void)
{
if( timer!= NULL )
{
del_timer( timer) ;
kfree( timer);
}
}
module_init(kerneltimer_init);
module_exit(kerneltimer_exit);
MODULE_LICENSE("Dual BSD/GPL");
리눅스 인터럽트
인터럽트를 처리하기 위해선 Linux에선 3가지 방법이 있습니다.
softirq, tasklet, work queue
가 그것이죠.
인터럽트란 HW적으로 CPU에 interrupt를 만들어 무엇인가 처리해야 할일을 처리하게끔(?) 만드는 역할을 합니다. 키보드를 누를때도 인터럽트가 발생하고, USB에 장치를 연결해도, 심지어 time tick을 처리하기 위해서도 1초에 300번정도(커널설정에 따라 변경 가능(i.e. 1000)) HW interrupt가 발생합니다. HW적으로 인터럽트핀이 CPU를 깨워서 인터럽트가 걸리면 맨앞 핸들러로 뛰어서 어떤인터럽트가 걸렸는지 확인하는 루틴이 실행됩니다. 이 루틴안에서 어떤 인터럽트인지 확인하고 다음처리를 담당하게 되죠. 그러나 주위해야하는점은 어떤 HW 인터럽트가 먼저 걸렸을때엔 다른 HW 인터럽트가 걸리지 않게 됩니다(인터럽트 pin을 SW적으로 내리기 전까진). 즉,응답성을 위해선 인터럽트 핸들러에선 정말 간단하게 어떤 인터럽트인지만 확인하고, 바로 인터럽트를 해제하지 않으면 그사이엔 어떠한 HW 인터럽트가 발생되지 않아 시스템의 응답성이 떨어지게 되겠죠.. 바로 HW인터럽트를 받아서 인터럽트핀을 해제하고 약간 지연되게 처리하는 방법이 위의 3가지라고 보시면 됩니다.
softirq
32가지 미리 정의된 인터럽트들을 정의하고, 인터럽트 핸들러가 종료되서 인터럽트 가능한 상태로 바뀌면 바로 softirq가 실행된다. 가장 높은 우선순위를 가지고 있으며, 고정된 인터럽트들을 처리하기 위해서 사용합니다. 현재 커널은 32가지중 6가지만 사용합니다. 종류는 HI_SOFTIRQ(높은 우선순위), TIMER_SOFTIRQ(타이머), NET_TX_SOFTIRQ(네트워크 패킷송신), NET_RX_SOFTIRQ(네트워크 패킷수신), SCSI_SOFTIRQ(SCSI), TASKLET_SOFTIRQ(태스크릿들)이고, HI_SOFTIRQ가 우선순위가 가장높게 처리됩니다.
tasklet
동적으로 할당된 softirq라고 생각하면 됩니다. 위 softirq의 SCSI_SOFTIRQ가 처리되고나서 TASKLET_SOFTIRQ가 처리되는데 이때엔 동적으로 할당을 받아서 처리하고 싶은 handler를 등록하고 처리하게 됩니다.
work queue
softirq나 tasklet들이 실행중에는 sw인터럽트중이라, hw 인터럽트는 가능하지만, 여전히 sw적으로 우선적으로 처리되는것들입니다. 즉 softirq중에는 user process들이나, context switch등은 처리되지 않고 있겠죠. 모든 sw irq를 softirq로만 처리한다면 user process나 context switch등은 처리안되어 유저입장에선 상당히 반응성이 안좋은 커널이라 생각할수 있습니다. 그래서 context switch등과 동일한 level에서 스케쥴링되는 work queue를 두어 sw interrupt들이지만 상당히 시간을 요하거나 계산해야될게 많은 작업들 혹은 휴면이 필요한 I/O작업이 필요한 일들은 context switch될때 같이 되게 만들어 주어 커널 응답성을 좋게 해줄수 있습니다.
ioctl() 디바이스 제어
디바이스 제어 ioctl() 함수의 역할
저수준 파일 입출력 함수인 ioctl()을 디바이스 파일에 적용시키면 디바이스 파일에 연결된 디바이스 드라이버의 파일 오퍼레이션 구조체의 ioctl 필드에 선언된 함수가 호출된다. ioctl() 함수는 디바이스 파일 이외에는 사용할 수 없는 디바이스 파일 전용 함수이므로 각 디바이스마다 고유하게 선언하여 사용한다. 그래서 read(), write()함수와 같이 정형화된 형태를 기본적으로 유지하지만, 사용 방법은 디바이스마다 모두 다르다. 저수준 입출력 함수인 ioctl() 함수와 디바이스 드라이버에 선언되는 ioctl() 함수의 매개변수 전달 관계는 아래와 같다.
위 그림과 같이 request는 응용 프로그램이 디바이스 드라이버에게 요구하는 명령어고, 이 request에 대입된 값은 디바이스 드라이버의 매개변수 cmd에 그대로 전달된다. 이 값은 디바이스 드라이버 작성자가 임의로 결정하는 사항이다. 하드웨어와 구현되는 디바이스 드라이버에 따라서 값이 전혀 다를 수 있다. 또 동일한 값에 대해 디바이스 드라이버마다 다르게 해석할 수도 있다. 매개변수 argp는 request에 따라서 선언해도 되고 선언하지 않아도 되는 가변 인자 매개변수다. 이 값은 request에 종속되어 디바이스에 전달한 정보를 담은 구조체 변수의 선두 주소를 전달하거나 디바이스 드라이버에서 얻고자 하는 정보를 담아올 수 있는 구조체 변수의 선두 주소를 전달한다. 특별한 경우에는 단순하게 상수값으로 사용할 수도 있다. argp 역시 어떻게 사용될 것인지는 디바이스 드라이버 작성자의 결정에 따라 달라진다.
ioctl() 함수의 특징
read(), write() 함수와 같이 쓰기와 읽기 처리가 가능
하드웨어의 제어나 상태를 얻기 위해 사용
응용 프로그램의 명령에 따라 디바이스 드라이버의 매개변수 해석이 달라짐
ioctl() 함수의 일반적인 형태
ioctl() 동작 개념
응용 프로그램에서 ioctl()함수를 이용하여 하드웨어를 제어하거나 상태를 읽기 위해서는 디바이스 파일을 제어하는 디바이스 드라이버에서 해석 가능한 명령과 구조체를 사용해야 한다. 프로그램을 구현하기 위해 ioctl() 함수를 사용할 때는 공통된 헤더 파일을 사용하게 되는데, 이 헤더 파일에는 ioctl에 전달되는 명령에 대한 선언과 명령을 처리하는 보조적인 정보를 주고받기 위한 구조체가 선언되어 있어야 한다. 디바이스 드라이버의 ioctl() 함수는 파일 오퍼레이션 구조체에 선언된 ioctl()함수가 호출되며, 이때 전달되는 매개변수값은 응용프로그램의 ioctl에서 전달하는 값을 그대로 전달받는다. 응용 프로그램에서 사용하는 매개변수는 응용 프로그램의 request와 argp에 해당하는 값만 전달 받는다. 디바이스 드라이버의 ioctl() 함수는 가장 먼저 전달된 cmd 명령이 유효한가를 확인한다. 전달된 명령이 유효한지 아닌지를 확인하기 위해 _IOC_NR과 _IOC_TYPE이라는 매크로 함수를 사용한다. 전달된 명령이 더 이상 유효하지 않으면, 즉 처리할 수 없는 명령일 경우엔 EINVAL이라는 음수값을 반환한다. 이와는 반대로 전달된 명령어가 정상적인 명령일 경우에는 명령이 읽기를 요구하는지 쓰기를 요구하는지를 검사한다. 이 검사는 _IOC_DIR이라는 매크로를 이용한다. 이 검사를 하는 주된 목적은 사용자 모드에서 메모리의 유효성을 검사하기 위해서이다. 이렇게 기본적인 검사가 끝났다면 switch문을 사용하여 명령을 구분하고 각 명령에 따른 처리를 구현하면 된다.
ioctl()에 전달되는 cmd와 관련 매크로 함수
cmd의 구성
디바이스 드라이버의 ioctl() 함수에 전달되는 매개변수 cmd는 응용 프로그램이 디바이스 드라이버에게 요구한 처리를 구별하기 위한 구별값이다. cmd에는 단순한 구별 숫자 이외에 처리에 도움을 주는 몇 가지 정보를 포함한 형태로 구성된다. cmd의 크기는 32비트로, 비트 구성은 다음과 같다.
매크로 함수
cmd에는 여러 가지 필드가 있다. 리눅스 커널은 이런 필드 형식에 맞춰 cmd 상수값을 만드는 매크로 함수와 cmd 상수값에서 필요한 필드값을 추출하는 매크로 함수를 제공한다.
cmd 명령을 만드는 매크로 함수
_IO : 부가적인 데이터가 없는 명령을 만드는 매크로
_IOR : 디바이스 드라이버에서 데이터를 읽어오기(R) 위한 명령을 만드는 매크로
_IOW : 디바이스 드라이버에서 데이터를 써넣기(W) 위한 명령을 만드는 매크로
_IOWR : 디바이스 드라이버에서 데이터를 읽고(R), 쓰기(W)를 수행하기 위한 명령을 만드는 매크로
이 매크로의 형태는 다음과 같은 형식의 값을 입력하도록 되어 있다.
_IO(매직번호, 구분번호)
_IOR(매직번호, 구분번호, 변수형)
_IOW(매직번호, 구분번호, 변수형)
_IOWR(매직번호, 구분번호, 변수형)
cmd 명령을 해석하는 매크로 함수
_IOC_NR : 구분 번호 필드값을 읽는 매크로
_IOC_TYPE : 매직 번호 필드값을 읽는 매크로
_IOC_SIZE : 데이터의 크기 필드값을 읽는 매크로
_IOC_DIR : 읽기와 쓰기 속성 필드값을 읽는 매크로
매직 번호
매직 번호값의 범위는 0~255 사이다. 보통 영문자 'A'~'Z' 또는 'a'~'z'를 넣는다. 이 매직 번호가 명령을 만들 때 특별한 의미가 있는 것은 아니다. 단지 디바이스 드라이버에서 이 매직 번호를 명령에서 추출하여 자신이 처리하는 매직 번호와 같은지를 비교하여 다르면 처리를 거부한다. 매직 번호는 잘못된 사용을 막는 초보적인 보안 장치다. 디바이스 드라이버에서 매직 번호를 추출하려면 다음과 같은 매크로를 사용한다.
_IOC_TYPE(명령) |
매직 번호는 가급적 다른 디바이스 드라이버와 다르게 하는 것이 좋다. 그렇다고 무조건 다르게 해야 한다는 말은 아니다. 다른 디바이스 드라이버에서 사용한 매직 번호를 사용해도 상관 없다.
구분 번호
구분 번호는 각 명령을 구분하기 위해 사용한다. 보통 0부터 순서대로 붙여나간다. 이 값은 같은 디바이스 드라이버에서는 중복해서 사용해도 된다. 예를 들어, 읽기와 쓰기 각각의 명령에 같은 구분 번호를 사용해도 디바이스 드라이버에서 명령을 구분할 때 switch문을 사용하면서 명령 매개변수인 cmd값을 그대로 사용하기 때문이다. 명령을 만드는 매크로에서 생성되는 값은 여러 필드를 조합하기 때문에 같은 구분 번호라 해도 다른 명령으로 인식할 수 있기 때문이다.
디바이스 드라이버가 명령에서 이 구분 번호를 추출하려면 다음 매크로 함수를 사용한다.
_IOC_NR(명령) |
하지만 switch문에서 각각의 case에 적용되는 값은 일반적으로 명령 자체를 쓴다.
변수형
변수형은 arg 매개변수가 가리키는 데이터의 전달 크기를 지정하는 것을 사용하는데, 숫자를 직접 대입하는 것이 아니고 변수형을 넣는다. 왜냐하면 명령을 만드는 매크로에 크기를 인식하는 sizeof란 컴파일 명령이 포함되어 있기 때문이다. ioctl을 사용할 때는 보통 구조체를 이용하여 구조체 주소를 arg에 넘기기 때문에 구조체형을 넣는 것이 일반적이다.
디바이스 드라이버에 전달된 명령에서 크기값을 추출하려면 다음과 같이 사용한다.
_IOC_SIZE(명령) |
_IO 매크로 함수
이 매크로는 전달되는 매개변수가 없고, 단순히 명령만 전달할 때 사용된다.
예를 들면, 다음과 같이 선언한다.
#define TEST_DRV_RESET _IO('Q', 0)
이때는 응용 프로그램에서 전달되는 arg 매개변수를 생량하거나 0을 대입한다. 이 매크로를 응용 프로그램에서 다음과 같이 사용할 수 있다.
ioctl(dev, TEST_DRV_RESET, 0); 또는 ioctl(dev, TEST_DRV_RESET);
이는 매개변수의 마지막 인자가 가변형 인자기 때문에 가능한 것이다.
이렇게 명령으로만 사용할 경우에는 데이터가 디바이스에 출력될 것인지 입력될 것인지에 대한 구분이 필요 없으므로 디바이스 파일의 열기 옵션에 대한 처리를 디바이스 드라이버에서 수행할 필요가 없다.
_IOR 매크로 함수
이 함수는 디바이스 드라이버에서 데이터를 읽어오는 명령을 만들 때 사용한다. 예를 들어, 다음과 같이 선언한다.
#define TEST_DRV_READ _IOR('Q', 1, int)
이는 디바이스에서 응용 프로그램이 읽어올 데이터의 크기가 int크기 만큼이라는 의미다. 디바이스 드라이버에 전달된 cmd 명령값에서 읽기용인지 쓰기용인지를 알아내기 위해 사용하는 매크로는 다음과 같다.
_IOC_DIR(명령) |
이 매크로를 수행했을 때 반환되는 값의 종류는 다음과 같다.
_IOC_NONE : 속성이 없다.
_IOC_READ : 읽기 속성이다.
_IOC_WRITE : 쓰기 속성이다.
_IOC_READ|_IOC_WRITE : 읽기, 쓰기 속성이다.
일반적으로 이 명령을 사용할 때, 응용 프로그램에서 ioctl()함수의 arg매개변수값은 디바이스 드라이버에서 데이터를 읽기 위한 데이터 버터(구조체)의 주소를 지정한다.
_IOW 매크로 함수
디바이스에 데이터를 쓸 명령을 만들 때 사용한다. 그 외의 내용은 _IOR과 같다. 일반적으로 이 명령을 사용할 때 ioctl()의 arg 매개변수값은 디바이스 드라이버에 데이터를 쓰기 위한 버터(구조체)의 주소를 지정한다.
_IOWR매크로 함수
디바이스에 데이터를 쓰고 읽기 위한 명령을 만들 때 사용한다. 그 외의 내용은 _IOR과 같다. 일반적으로 이 명령을 사용할 때 ioctl()의 arg매개변수값은 디바이스 드라이버에서 데이터를 쓰고, 읽기 위한 데이터 버퍼(구조체)의 주소를 지정한다.
출처 : http://blog.naver.com/luis8282?Redirect=Log&logNo=20086600288
Debian apt-get 공개키 에러 발생시...
debian 계열에서 apt-get update를 하다가 보면 공개키가 없다고 에러가 나올때가 있다. 문제가 되는 공개키를 B5B7720097BB3B58라고 하면, 아래와 같이 하면 해결 할 수 있다. (아래의 공개키는 emdebian archive의 키)
아래의 명령어로 필요한 공개키가 추가 되었음을 확인 할 수 있다.
|