팁이라기 보다는 문제 제기에 가깝습니다. 

리눅스에서 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:/ 

하니까 못 긁어가네요. 

더좋은 방법이 있는지 모르겠습니만... 
참고하시기를...

 

====================

오늘도 wget 여러 옵션들을 테스트해봤습니다. 
그동안 제일 궁금했던 것이 
--user-agent=agent-string 
등으로 user-agent를 속이는데 서버에서는 어떻게 인식하는지가 제일 궁금해서 
http://browsers.garykeith.com/tools/your-browser.asp 
에 접속해봤습니다. 

 wget  --user-agent="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"  http://browsers.garykeith.com/tools/your-browser.asp 
했더니 튕기더군요. 
---------------------------------- 
Access Denied 
You do not appear to be using this form in accordance with my Terms of Use. 
Continued abuse will eventually result in you losing access to this server! 
It's also possible you are using security software that modifies the HTTP_REFERER header. 
If I can't confirm the referrer is valid then you can't have access to my forms. 
-------------------------------- 

그래서 이번에는 --referer 옵션까지 설정을 해서 다시 시도해봤습니다. 
wget  --user-agent="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"  --referer="http://browsers.garykeith.com/tools/property-docs.asp" http://browsers.garykeith.com/tools/your-browser.asp 
이번에는 성공!!! 
------------------------------- 
Your Browser 
User Agent 
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) 
.... 이하 생략 
-------------------------------- 

어찌보면 당연한 결론이지만  --user-agent, --referer 두가지다 제대로 작동합니다. 

더 무서븐것은 --save-cookie, --load-cookies,  --post-data=string, --post-file=file 입니다. 

--save-cookie "cookie.txt" --post-data "user_id=myid&password=mypassword" 
옵션을 주니까 멋있게 로그인까지 하고 쿠키를 저장해두더군요. 

다시 
 --load-cookies "cookie.txt" 하니까 회원만 가능한 곳 어디든지 정상접속됩니다. 

post.dat라는 화일에 게시판에 필요한 변수를 입력해두고 
 --load-cookies "cookie.txt"  --post-file "post.dat" 하니까 게시판에 글도 씁니다. 

잘만 활용하면 좋겠는데 
까딱하면 스팸로봇이 따로 필요없습니다...헐~~

 

출처

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

관련된 이론 분야 : 운영체제론

 

크리티컬 섹션(임계구역) / 뮤텍스(상호배제) / 세마포어

이것들은 한양대 컴공과 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 캐릭터셋으로 변경하기위한 방법은 여러가지 작업을 거쳐야하는 까다로운 작업이다. 

새로운 사이트를 구축하는데는 별다른 어려움이 없지만

기존사이트를 이전하기 위해서는 알게 모르게 많은 수작업이 

들어간다. 

만일 HTML 파일내용을 EUC-KR에서 UTF-8로 변경해야 할 

경우라면 다음과 같은 명령을 사용한다.

iconv -c -f euc-kr -t utf-8 a.html > a.html.utf8

iconv 명령은 여러개의 파일을 동시에 변환할 수 가 없다. 따라서

여러개의 파일 혹은 디렉토리상의 HTMl을 변경하고자 할때는

다음과 같이 크립트를 작성하여 변환을 해야 한다. 


#!/bin/bash
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


사용형식 [찾을 디렉토리경로] [찾기옵션] [찾은후행할 작업]

 

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

[출처] find 명령어 |작성자 케이

리다이렉션과 파이프

 

시스템에 로그인하면쉘은 기본적으로 표준 입력장치로 키보드표준 출력장치로 모니터를 설정한다.

리눅스 시스템에서 리다이렉션과 파이프

-       입력과 출력의 방향을 변경할 수 있다.

 

리다이렉션

 

표준 출력의 리다이렉션

-       화면 출력을 파일 출력으로 바꾸는 것

-       리다이렉션을 의미하는 문자 è ‘>’

n  ex)  $ ls –al > test
이렇게 입력하였을 때 명령이 실행된 결과가 test 파일에 저장

-       파일이 이미 존재하고 있더라도 해당 파일을 무조건 덮어 씌우므로..
‘>>’ 
을 사용하여 이미 존재하는 파일의 끝에 추가하여 쓰도록 한다.

n  ex) $ ls –al >> test2
   $ cat test2
   $ ls –al >> test2
   $ cat test2

 

표준 입력의 리다이렉션

-       표준입력을 키보드에서 파일로 바꾸는 것

 

* sort 명령어 : 키보드로부터 입력된 데이터를 오름차순으로 정렬하여 그 결과를 표준 출력장치인 모니터 화면에 보여주는 명령어

 

-       표준 입력의 리다이렉션 è ‘<’

n  ex)  $ sort < names
          names 
파일로부터 입력받아 그 결과를 표준출력장치인 화면에 출력

n  ex)  $ sort < names > sorted
          
표준 입력과 표준 출력을 동시에..

 

 

 

파이프라인

 

파이프

 - 어떤 명령의 실행결과를 다음 명령의 입력 값으로 만들기 위해 두 명령어를 같이 쓸 수 있게 해주는 것!

파이프를 만들기 위해 두 명령어 사이에 | (vertical bar)를 놓아야 한다.
두 명령어 사이에 | 가 놓이면, | 을 기준으로 왼쪽은 표준 출력 명령이 되고오른쪽은 표준 입력 명령이 된다.

n   표준 출력 | 표준 입력

 ex)  cat names | sort | more
cat 
명령은 names 파일을 표준 출력하고, sort 명령은 cat에서 표준 출력된 데이터를 입력 값으로 받아 정렬한다정렬된 데이터를 다시 표준출력하며, more 명령은 sort에서 정렬된 데이터를 출력한다.

 

 

 파이프라인 분리 - Tee

 

파이프라인 분리

-       하나의 입력을 가지고 두 개의 동일한 출력을 가지는 명령어
파이프에 tee를 위치시키면 입력 데이터에 대한 두 개의 동일한 출력을 만들어 낼 수 있다는 것!

-       일반적 형식

n  tee filename

n  ex ) $ cat  names   sort  |  tee  sorted  | pr
          
파이프라인 tee를 이용해 데이터를 정렬하여 sorted라는 이름으로 저장하고 인쇄하는 예


출처 : http://blog.naver.com/dbwls0105?Redirect=Log&logNo=30037806187

리눅스 터미널을 열었는데

쉘 프롬프트 모양이

 

bash-3.1#

 

이런식으로 나와 있을 경우가 있습니다.

이런경우 현재 디렉토리 위치도 모를뿐더러 현재 user가 누군지도 모릅니다.

 

vi .bashrc 를 열어서

export PS1="[\u@\h \W]\$"  를 추가해줍니다.

 

source .bashrc를 통해 bashrc를 다시 읽습니다.

 

 

옵션)

\t 현재 시간을 HH:MM:SS 형식으로 보여준다.
\d 날자를 "요일 월 일" 형식으로 보여준다. Tue Jan 23
\s 쉘의 이름을 보여준다.
\w 현재 작업디렉토리를 완전경로로 보여준다.
\W 현재 작업디렉토리의 이름을 보여준다.
\u 현재 사용자의 사용자명
\h 호스트만
\H 호스트이름전체
\# 현재 명령의 명령 번호
\$ root이면 #, 일반사용자이면 $
\! 이 명령의 히스토리 번호
\nnn 8진수 nnn에 해당하는 문자
\[ 비출력문자의 시퀀스를 시작한다.
\] 비출력문자의 시퀀스를 마친다.

 

 

참고)

- Ubuntu 기본 프롬프트
PS1="${debian_chroot:+($debian_chroot)}\u@\h:\w\$" 
 
- CentOS 기본 프롬프트
PS1="[\u@\h \W]\$"

하드웨어 상태를 주기적으로 감시할때 정해진 시간이 초과되면 특정 함수를 수행하는 기능을 한다. 리눅스 커널은 타이머 인터럽트가 발생하며 스케줄링에 필요한 처리를 끝낸 후 커널 타이머 목록이라는 데이터 구조를 검사하며, 이 커널 타이머 목록은 수행할 함수와 처리되어야 할 시간에 대한 정보가 담긴 연결 리스트이다.

커널 타이머 이용시

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될때 같이 되게 만들어 주어 커널 응답성을 좋게 해줄수 있습니다.

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

디바이스 제어 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

[출처] 디바이스 제어|작성자 piao


debian 계열에서 apt-get update를 하다가 보면 공개키가 없다고 에러가 나올때가 있다.
문제가 되는 공개키를 B5B7720097BB3B58라고 하면, 아래와 같이 하면 해결 할 수 있다.
(아래의 공개키는 emdebian archive의 키)

insidexino@insidexino-desktop:~$ gpg --keyserver wwwkeys.eu.pgp.net --recv-keys B5B7720097BB3B58
gpg: requesting key 97BB3B58 from hkp server wwwkeys.eu.pgp.net
gpg: key 97BB3B58: "Emdebian Archive Signing Key" not changed
gpg: Total number processed: 1
gpg:              unchanged: 1
insidexino@insidexino-desktop:~$ gpg --list-keys 97BB3B58
pub   1024D/97BB3B58 2007-04-30
uid                  Emdebian Archive Signing Key
sub   2048g/FEFD537E 2007-04-30

insidexino@insidexino-desktop:~$ gpg --export 97BB3B58 > 97BB3B58.gpg
insidexino@insidexino-desktop:~$ sudo apt-key add ./97BB3B58.gpg 
OK


아래의 명령어로 필요한 공개키가 추가 되었음을 확인 할 수 있다.

insidexino@insidexino-desktop:~$ sudo apt-key list
/etc/apt/trusted.gpg
--------------------
pub   1024D/97BB3B58 2007-04-30
uid                  Emdebian Archive Signing Key
sub   2048g/FEFD537E 2007-04-30

+ Recent posts