레이블이 linux인 게시물을 표시합니다. 모든 게시물 표시
레이블이 linux인 게시물을 표시합니다. 모든 게시물 표시

2010년 9월 10일 금요일

There is no /dev/dsp !!!!


sound card 테스트를 좀 하려고 하는데 /dev/dsp가 없는거다.
게다가 /dev/audio도 없는거다!!
뭐야 이게. ㅠ_ㅠ

우선, mac에서는 이러한 것들을 다 막아놓은 것 같다.
(사실 처음에 mac에서 시도 했더랬다. 그것도 unix니까.)
워낙 애플이 DB와 Device에 대해서 단단히 닫힌 마인드로 보여주지 않고 있다는 것은 알고 있었던 사실, 그래서 fedora13이 설치되어 있는 컴퓨터에서 다시 시도 했는데, /dev/dsp가 없었다.

그래서 만들었다. = _=);

$ modprobe snd-pcm-oss

이 명령어를 수행하면
/dev/audio
/dev/dsp
/dev/mixer
... 가 생긴다. -_-)b

2010년 7월 29일 목요일

svn+ssh:// 자동 로그인


subversion을 ssh로 세팅해놨더니만 정말 불편한게..
뭘 할 때마다 비밀번호를 3~4번씩 입력을 해야된다는 거다.
아파치 서버로 세팅해놨을 때는
비밀번호 저장하는 체크박스가 하나 있어서 그걸 체크해 두면 알아서 다 됐는데 말이다. ㄱ-);
이게 너무 귀찮아서 자동로그인을 하려고 좀 알아봤는데..
이걸로 무려 이틀이 넘게 삽질을 했다.  아우 짜증나.. = _=);


아무튼 고고!


1. SSH 자동 로그인 하기

우선 클라이언트 쪽에서 Key를 생성해 보자. (서버 쪽에서 해도 상관없다.)
나는 cygwin을 사용하고 있기 때문에 리눅스 명령어 쯤이야 OK.
$ ssh-keygen -t rsa
$ ls
ssh-keygen 명령을 실행시키면 몇 가지를 물어보는데 첫 번째는 키를 생성할 디폴트 디렉토리 이다. 나중에 이쪽으로 가서 ls로 확인을 하면된다.
두 번째는 키의 password이다. 그냥 엔터를 내리 치면 나중에 ssh 자동접속 할 때 암호를 안물어 보게 된다.
세 번째는 당연히 password 확인이므로 아까 입력한 것과 같은 값을 입력하면 된다.

ssh-keygen 명령으로 rsa 키를 생성하고 ls를 실행시켜보면,
id_rsa와 id_rsa.pub가 생성된 것을 볼 수 있다.
id_rsa.pub는 공개키로 서버가 가지고 있어야 할 것이고, id_rsa는 클라이언트가 가지고 있으면 된다.

자, 그럼 공개키를 서버로 보내주자.
$ scp -p id_rsa.pub username@서버주소:.ssh/authorized_keys
여기서 username은 자신의 계정이고, 서버주소는 ssh로 접속할 서버의 주소이다.
ip주소를 써도 되고.. 그건 서버 나름.

위와 같이 쓰고 엔터를 치면, username의 홈디렉토리에 있는 .ssh폴더 아래 authorized_keys 파일로 복사가 된다.
여기서 파일이름은 꼭 authorized_keys로 해주어야 하는데, 이것은 config파일에 그렇게 명시가 되어 있기 때문이다.
이걸 구지구지 꼭 욕심내서 이름을 내맘대로 하고 싶다고 하면 /etc/ssh/sshd_config 파일을 고치면 된다. (root 계정만 접근 가능하다)

만약 .ssh 폴더가 홈디렉토리내에 없으면 에러가 날 수 있다.
ssh 비밀번호를 물어보게 되는데 일단은 서버에서 사용하는 비밀번호를 입력하여 파일을 보낸다.

이제 클라이언트에서 할 일은 다 끝났다. 접속해보자.
$ ssh username@서버주소
아까 key를 생성할 때 비밀번호를 입력했다면 그 비밀번호를 입력하라고 할 것이고,
그냥 enter만 연신 눌렀다면 바로 그냥 접속이 된다.

만약 아까 key를 생성할 때 비밀번호를 입력했음에도 불구하고 비밀번호를 입력하기 귀찮다면,
다음과 같은 명령어를 수행한다.
$ eval $(ssh-agent)
$ ssh-add
첫 번째 줄 명령어를 수행하면 agent pid 어쩌고 라는 글이 뜬다.
그 때 add 명령어를 수행해주면 비밀번호를 입력하지 않고도 무사히 접속 가능하다.



2. 키 저장하기

만들어 둔 키를 저장해보자.
그러기 위해서는 puttygen파일이 있어야 한다. (다운로드하러가기)
load를 클릭하여 위에서 만든 key를 찾아 load한다.
이 때 pub key를 load하는 것이 아니라 'id_rsa' 파일을 load한다.

load를 하면 key가 뭐라고 뭐라고 뜨는데, 이 때 "Save private key"를 클릭하여 그 키를 적당한 곳에 저장한다. 이름도 지정해주고 확장자는 'ppk'이다.



3. Subversion에서도 자동로그인!!

우선 subversion으로 공유할 폴더를 하나 만든다.
나는 D:\test라고 만들었다. (이건 뭐 상관없다..-_-; 아무의미도 없고;;)
폴더를 만들었으면 폴더에 마우스를 갖다대고 우클릭!!

TortoiseSVN > Setting > Network
하단에 SSH client: 부분에다가 다음과 같이 입력한다.
"C:\Program Files\TortoiseSVN\bin\TortoisePlink.exe" -ssh -l username -i"C:\cygwin\home\.ssh\svnTest.ppk" -P 22

여기서 첫 번째 경로는 TortoisePlink.exe의 경로이고 두 번째 경로는 저장한 키(.ppk)가 있는 경로이다.
그리고 username에는 ssh에 로그인할 때 사용할 이름을 입력한다.
마지막 숫자는 ssh의 port번호인데 기본적으로는 22번을 사용한다.

이렇게 해두고 svn에 update나 commit을 위해 접근하면 key에서 사용한 비밀번호를 물어보게 된다.
물론 비밀번호를 지정하지 않았다면 묻지 않겠지만,
비밀번호를 입력했다면 묻는것이 당연하다.



4. pageant 사용

위의 과정에서 비밀번호를 매번 입력하지 않게 하기 위해서 pageant라는 프로그램을 사용한다.
pageant 프로그램도 putty 다운로드 사이트에서 받을 수 있다. (다운로드받으러가기)
다운받아 실행시키면 다음과 같은 창이 뜬다.
여기서 AddKey를 눌러 아까 ppk로 저장해 두었던 파일을 불러온다.
그러면 key가 등록이 된다.
여러 개를 등록할 수도 있다.

이 프로그램을 사용하면, 처음에 컴퓨터를 켤 때만 비밀번호를 입력한 후 그 이후로는 자동으로 로그인 되어 사용할 수 있다.
죄측 하단에 트레이 아이콘으로 계속 살아있다.





덧,

2010년 6월 24일 목요일

SubVersion 설정



우선, subversion의 server는 llinux fedora12이며, client는 windows XP임을 밝혀두는 바이다.




1. Subversion 설치


처음에 subversion을 설치할 때 삽질을 엄청나게 했는데, 설치는 매우 간단하다.
rpm 패키지로 배포하고 있으므로 간단하게 yum명령어를 사용하여 설치할 수 있다.

$ yum install subversion


설치를 하고 나면 앞으로 SVN 파일들을 관리할 폴더를 하나 만들어 주고, 그 안에 SVN을 설정한다.
나는 home 디렉토리 밑에 svn을 하나 만들고 svn이 제대로 작동하는지 알아보기 위해서 test 디렉토리를 하나 만들어 svn저장소로 사용하고 세팅 되었는지 확인했다.

$ cd /home
$ mkdir svn
$ cd svn
$ svnadmin create test

svnadmin 명령어를 사용하면 svn저장소 디렉토리를 생성한다.
파일시스템 타입을 지정해주고 싶다면 다음과 같이 사용하여도 된다.

$ svnadmin create --fs-type fsfs test (파일시스템)
$ svnadmin create --fs-type bdb test (버클리DB)


test 디렉토리 안에 가보면 svn저장소를 위한 파일들이 생성되어 있음을 볼 수 있다.
이제, client에서 svn저장소에 접속할 수 있도록 설정해주어야 하는 작업이 남아있는데, 이 작업은 3가지 방법으로 할 수 있다.
첫 번째는 svnserve ID로 인증받는 법, 두 번째는 ssh를 사용하는 것, 세 번째는 apache를 연동하여 사용하는 법이다.

나는 첫 번째, 두 번째 방법으로만 해보았는데, apache를 연동하는 방법도 많이 쓰이고 있는 것 같더라.
근데 apache를 세팅하려면 뭘 또 많이 깔고 삽질을 해야되서 귀찮아서 이 방법은 안 써봤다;;;




2-1. svnserve ID 인증 방법으로 설정하기


우선, 첫 번째 방법부터 소개하도록 하겠다.
svnserve ID로 인증 받는 것은 아무래도 최신 subversion에서만 가능한 것 같다.
근데 이 방법은 문제가 있는데, passwd 파일이 전혀 암호화 되어 있지 않다.
그래서 passwd파일에 접근 권한만 있다면 누구든지 svn저장소 사용자들의 id와 password를 알 수 있다.
혼자 쓰는 것이 아니면 별로 권해주고 싶은 방법은 아니다.

위에서 svn저장소로 생성한 디렉토리에 가보면 svnserve의 설정 파일이 존재한다.
conf 디렉토리 밑에 svnserve.conf 라는 파일이다.
(위에서와 같이 생성한 경우, 절대 경로는 "/home/svn/test/conf/svnserve.conf" 이다)
처음 이 파일은 죄다 주석처리가 되어있기 때문에 아무런 설정도 되어있지 않은 상태이다.
이 파일의 "[general]"부분에서 몇 군데 주석을 풀고 설정을 할 것이다.

[general]

... 중략 ...

anon-access = none //아무나 접근할 수 없게 함
auth-access = write //인증된 사용자에게만 쓰기 권한을 줌

...

password-db = passwd

....

realm = My First Repository

설정을 했으면 저장하고 나와서 같은 디렉토리내에 있는 passwd 파일을 열어서 편집한다.
$ vi passwd

test = 1111
이렇게 써주면 id는 test고, password는 1111이라는 뜻인데, 전혀 암호화 되어 있지 않다.

다 되었으면 저장하고 나와서 테스트를 한번 해보자.

$ svn checkout svn://10.0.0.1/test test

10.0.0.1은 pc의 IP주소이다.

id와 password는 위에서 passwd 파일에 저장했던 것을 사용한다.
처음 테스트를 할 때, "Store password unencrypted (yes/no)?" 이런 문구가 뜰지도 모른다.
물론 yes 또는 no를 입력하면 되는데,
yes를 치든, no를 치든 계속 다시 물어보는 경우에는 한국어로 "예"라고 치면 넘어간다.
(진짜 황당했다;;)
"checked out revision 0" 라고 뜨면 설정 완료.




2-2. SSH를 이용한 방법으로 설정하기


이 두 번째 방법을 사용하기 위해서는 ssh가 설치되어 있어야 한다.
ssh가 구동되고 있어야 사용할 수 있다.

아무튼 이 방법은 어떻게 보면 첫 번째 방법보다 더 쉬울 수 있다.
위에서 설명한 방법은 사용자 id와 passwd를 일일이 적어주어야 하는 번거로움이 있었지만, 이 방법은 이미 linux pc 상의 사용자들을 추가만 해주면 된다.

subversion의 config파일에 사용자만 추가해 주면 되는데, 이 파일은 홈디렉토리에 있다.

$ cd
$ cd .subversion
$ vi config

이 파일도 많은 설정을 해두고 있는데 그 중에서 'tunnels'라는 부분을 찾아서 기존에 있던 linux 사용자들의 이름을 추가해 주면 된다.

[tunnels]
ssh = ssh -l test

저장하고 빠져나와서 테스트를 한 번 해보자.

$ svn checkout svn+ssh://10.0.0.1/home/svn/test

password는 linux pc에서 사용하는 비밀번호를 사용하면 된다.
그럼 위에서 했던 것처럼 체크아웃 된 리비전을 보여준다.

이 때 주의해야 할 점은 /home/svn/의 경로까지 다 써주어야 한다는 점이다.
위에서 사용한 방법은 /home/svn/하위의 상대 경로만 써주어도 접근이 가능하지만, ssh를 이용한 방법은 절대 경로를 통해 접근한다.

만약 원하는 사용자로 로그인하여 들어가고 싶으면 다음과 같이 사용한다.

$ svn checkout svn+ssh://test@10.0.0.1/home/svn/test




3. client에서 접속하기


windows client에서 설정을 끝낸 subversion server에 접근을 해보도록 하겠다.
windows에는 subversion이 설치되어 있을 것이라고 생각하고 진행한다. (tortoiseSVN 다운로드)


- svn저장소로 쓸 폴더를 아무곳에나 만든다.
(아래의 이미지에서 보면 svn저장소로 쓸 폴더를 D:\아래 test라는 이름으로 만들었다.)
- 새 폴더를 만들었으면, 새 폴더 위에서 마우스 오른쪽 버튼을 클릭한다.
(이 때 만약 svn관련된 메뉴가 없다면, subversion 설치가 안된 것이거나 잘못 된 것이다.)
- SVN checkout을 선택하면 다음과 같은 창이 나타난다.
- URL of repository: 란에 아까 test할 때 넣었던 경로를 적는다.
첫 번째 방법을 사용한다면 "svn://10.0.0.1/test" 라고 입력하고
두 번째 방법을 사용한다면 "svn+ssh://test@10.0.0.1/home/svn/test"라고 입력한다.

- Checkout Directory 란은 svn저장소로 쓸 폴더를 말한다.

- OK버튼을 누른다.
(password를 입력하고 revision이 뜬다면 OK!!)




덧, KLDP wiki에 subversion-HOWTO 문서가 있는데 굉장히 잘 정리가 되어있다.
다만 너무 길어서 다 보기는 힘들고.. 때때로 찾아보면 좋을 것 같다.
나도 이 문서를 많이 참고 했다. 보러가기

2010년 6월 21일 월요일

clamAV(Anti Virus) 설치

별것도 아닌 것 때문에 삽질을 좀 많이 하긴 했지만.
(외부 인터넷이 연결이 안되어 있었다;;)
yum으로 설치가 되기 때문에 설치는 어렵지 않다.

$ yum list clamav* (clamav 목록 확인)
$ yum install clamav

설치가 끝나면 검사를 해준다.
검사를 원하는 directory로 이동을 한 후, clamscan 명령을 사용한다.
아래 사용은 root directory로 이동하여 전체 파일을 검사하였다.
$ cd /
$ clamscan -r

전체 다 하려니 시간은 좀 걸린다.


남은 것은 설정과 업데이트인데.... 이건 삽질을 좀 더 해봐야겠다.
그나저나.. AV래니까 자꾸 이상한 쪽으로 생각을 하게 되는건 나뿐인가?!

2010년 6월 1일 화요일

네트워크 설정


네트워크 설정을 위해 수정할 파일들

/etc/resolv.conf
/etc/sysconfig/network/scripts/ifcfg-eth0


우선, resolv.conf는 도메인서버를 저장할 파일이다.
파일을 열어 도메인네임서버를 지정한다.

$ vi /etc/resolv.conf
nameserver 168.126.63.1
nameserver 168.126.63.2
(KT 네임서버임.)


/etc/sysconfig/network/scripts 밑에 생성된 파일들을 살펴보면 ifcfg- 형태의 파일이 여러가지가 있다.
ifcfg- 뒤에 붙는 것은 하드웨어 이름으로 lo는 loopback을 뜻한다.
랜카드가 여러개라면 eth0, eth1.. 이렇게 될 수도 있으니 설정하길 원하는 하드웨어 이름이 붙어있는 파일을 열어 수정한다.

$ vi /etc/sysconfig/network/scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=static
ONBOOT=yes
TYPE=Ethernet
NETMASK=255.255.255.0
IPADDR=192.168.10.101
GATEWAY=192.168.10.1
USERCTL=no
PEERDNS=yes
IPV6INIT=no
뭔가 굉장히 많이 설정해 준 것 같지만,
IPADDR, GATEWAY, NETMASK만 원하는 값으로 설정해주면 된다. -_+)b
동적 IP를 할당할 시에는 BOOTPROTO=dhcp로 설정한다.


모든 설정이 끝나면 네트워크를 재시작하고 설정이 잘 되었는지 확인해본다.

$ /etc/init.d/network restart
$ ifconfig

2010년 5월 31일 월요일

X window 설치 명령어


X window는 기본적으로 리눅스를 설치할 때 함께 설치 되지만 그렇지 않은 경우도 종종 있어 수동으로 콘솔 창에서 설치하는 법도 알아 두어야 할 것 같다.


$ yum grouplist

위의 명령어를 사용하게 되면 나열된 group list를 볼 수 있는데, 아래 쪽에 "X window system"이라고 있는 것이 있다.
이것을 찾았다면 설치 해보자.


$ yum -y groupinstall "x window system"

.. 하면 x window 시스템 패키지가 설치가 된다.
설치가 완료 되면 xorg 패키지도 설치를 해준다.

$ yum install xorg*


그리고 configuration 파일을 만들기 위해서, (물론 자기가 일일이 만들어도 되지만;) 다음을 수행한다.

$ xorgconfig

configuration이 끝나고 configration 파일을 약간 수정하려면 /etc/X11/xorg.conf 파일을 수정한다.
모니터의 해상도 등을 조절할 수 있다.

2009년 10월 20일 화요일

ip 주소 설정/변경하기

리눅스에서 ip주소를 설정하기 위해서는 3개의 파일을 수정해야 한다.

- /etc/sysconfig/network-scripts/ifcfg-eth0
- /etc/sysconfig/network
- /etc/resolv.conf




IP주소와 Broadcast, Netmask, Network addr를 수정하고 싶으면 ifcfg-eth0 파일을 수정한다.
이 파일을 열어보면,

DEVICE=eth0
BOOTPROTO=static
ONBOOT= yes

이라고 되어있는 것을 볼 수 있는데,
만약에, 동적으로 ip를 할당해서 사용한다면 DHCP로 되어있을 것이다.
DHCP로 되어 있는 경우에는 ip주소 및 다른 주소들이 필요하지 않다.

고정ip를 사용하는 경우에는, 나머지 주소를 입력해준다.

IPADDR=10.0.0.1 (원하는 ip주소를 입력한다.)
BROADCAST=10.0.0.255 (xxx.xxx.xxx.255를 입력한다. 앞에 x부분은 대부분의 경우 ip와 같다.)
NETMASK=255.255.255.0
NETWORK=10.0.0.0 (xxx xxx.xxx. 0을 입력한다.)




Gateway를 수정하고 싶으면 network 파일을 수정한다.
이 파일을 열어보면

NETWORKING=yes
HOSTNAME=어쩌고 (이것도 수정 가능하다.)

여기에 Gateway를 입력한다.

GATEWAY=10.0.0.254 (xxx.xxx.xxx.254를 입력한다.)




DNS를 수정하고 싶으면 resolv.conf 파일을 수정한다.

nameserver xxx.xxx.xxx.xxx
nameserver xxx.xxx.xxx.xxx

첫 번째 적는 것이 1차 네임 서버, 두 번째 적는 것이 2차 네임 서버이다.




파일의 수정이 끝났으면 네트워크를 다시 시작한다.

$ service network restart

2008년 11월 24일 월요일

시스템 콜 추가

1. system call 함수 선언

asmlinkage 반환형 sys_함수이름 ( arg1, arg2.......)
{
//To do
}


2. system call 번호 추가

include/asm/unistd.h 파일을 수정한다.
맨 아래쪽에 __NR_함수이름을 쓰고 번호를 지정해준다.


3. system call table에 추가

arch/i386/kernel/entry.S 파일을 수정한다.
ENTRY(sys_call_table) 이라고 되어있는 곳 맨 끝에 새롭게 정의한 시스템콜 함수 이름을 적는다.
.long sys_함수이름


4. 커널컴파일

$ make


2008년 10월 15일 수요일

autogen 사용


1. Makefile.amMakefile.in을 복사해온다. (귀찮으니까)


2. 컴파일 할 소스와 같은 디렉토리 내에 있는 Makefile.am을 열어서 실행파일 이름을 바꾼다.
noinst_PROGRAMS 라고 되어 있는 부분에 이름을 바꾸면 된다.
이 이름을 바꾼후에 OURCES와 LDADD도 실행 파일이름으로 바꾸어 주어야 한다.
만약, 실행파일 이름이 test라면,

noinst_PROGRAMS = test
test_SOURCES = 소스파일
test_LDADD
... 이런식으로 수정한다.


3. 만약 상위디렉토리가 있다면 그곳에 있는 Makefile.am도 수정한다.
SUBDIRS에다가 새로 만든 디렉토리 이름을 추가한다.


4. autogen이 있는 곳에 configure.ac 라는 파일을 수정한다.
AC_CONFIG_FILES 에 현재 디렉토리로부터 새로 만들 Makefile의 경로를 써준다.


5. autogen실행
$ ./autogen.sh
아무런 메세지가 뜨지 않은 다면 성공.


6. 적절한 옵션과 함께 configure하고 나면 4단계에서 지정해준 경로에 Makefile이 생성되어 있을 것이다.


7. 컴파일 한다.
$ make
그럼 실행파일이 생성된다.

2008년 8월 4일 월요일

리눅스에서 윈도우 원격접속

리눅스에서 윈도우로 원격접속을 하려면 여러가지 방법이 있지만, 그 중에 rdesktop을 이용하는 것이 가장 일반적이다.

rdesktop으로 원격접속을 해보자.


1. install

rdesktop 다운로드
다운로드를 받고 압축을 푼다.

압축을 푼 디렉토리로 이동하여 다음 명령어를 수행한다.
$ ./configure (몇몇 패키지가 설치되어 있지 않다고 투덜대면 패키지를 설치하고 다시 한다.)
$ make
$ make install


2. 사용하기

위와 같은 방법으로 rdesktop을 설치하였다면 이제 사용하면 된다
$ rdesktop -a 16 -f  ipaddr

-a는 해상도 옵션(16bit을 의미)
-f는 fullscreen이다.

윈도우 화면이 뜰 것이다+_+!
와우.

2008년 8월 1일 금요일

nfs 설치

1. install
  우선, nfs 패키지를 인스톨 해야한다.

  $ yum install nfs-util (맞나? 암튼 비슷한 이름의 패키지이다;;)


2. 설정
  /etc에 가보면 exports라는 파일이 있다.
  그 파일을 열어보면 아무것도 없을 수도 있고, default로 뭔가 저장되어 있을 수도 있다.
  이 파일을 수정하여 nfs를 동작하게 한다.

  /nfsroot localhost(rw,insecure,root_squash)
  /nfsroot 192.168.11.*(rw,insecure,root_squash)

  이런식으로 설정해 줄 수 있다.
  /nfsroot는 서버의 nfs directory이며 localhost라든가 192.168.11.* 등의 address는 이 폴더(nfs directory)에 접근할 수 있는 권한을 줄 client를 말한다. 그리고 괄호안에 들어가있는 내용은 권한에 관련된 것이다.


3. 재시작
   $ /etc/init.d/nfs restart

  설정을 변경해주었으므로 재시작 한다.


4. 테스트 하기
   잘 설치되었는지 보려면 테스트를 해본다.
   $ mount -t nfs localhost:/nfsroot /temp
   라고 입력하면 자기 컴퓨터의 /temp와 /nfsroot가 연결된다.

  /nfsroot에 파일을 생성하거나 수정을 하면 /temp에도 똑같이 적용된다.

2008년 3월 28일 금요일

리눅스 커널 2.4 - scheduling 과정 중 context switching



/usr/src/linux-2.4.20-8/kernel/sched.c

 

/*

* context_switch switch to the new MM and the new

* threads register state.

*/

static inline task_t * context_switch(runqueue_t *rq, task_t *prev, task_t *next)

/*

* rq(runqueue_t)

* prev(task_t): 현재 실행되고 있는 process

* next(task_t): scheduling받아 이제 실행 될 process

*/

{

           struct mm_struct *mm = next->mm;

           struct mm_struct *oldmm = prev->active_mm;

 

           if(unlikely(!mm)) //이전 process(prev)와 주소공간 공유

           {

                     next->active_mm = oldmm;

 //이전 process(prev) active_mm을 갖는다

                     atomic_inc(&oldmm->mm_count);

//oldmm reference count 증가

                     enter_lazy_tlb(oldmm, next, smp_processor_id()); //TLB설정

           }

           else //다른 주소공간을 가진 process일 경우

                     switch_mm(oldmm, mm, next);

//switch_mm을 호출하여 주소공간switch

          

if(unlikely(!prev->mm)) //현재process(prev) mm포인터가 null이라면

           {

                     prev->active_mm = NULL;

//prev active_mm null로 만들어준다.

                     rq->prev_mm = oldmm;

           }

 

           /* Here we just switch the register state and the stack. */

           switch_to(prev, next, prev); // CPU dependent한 매크로

 

           return prev;

}

 

   이 함수는 schedule() 함수에서 호출된다. scheduler가 다음 수행 될 process를 고르고 나서 호출하는 함수가 바로 이 context_switch함수이다. 현재 수행되고 있는 process의 정보와 다음 수행 될 process의 정보를 argument로 넘겨받는 context_switch함수는 가장먼저 process를 메모리 상에 올리는 일을 수행 한다.  scheduling에 의해 선택되어 다음 번에 실행 될 processmemory management(task_struct안의 mm_struct)  NULL일 경우에는 수행되던 process의 주소공간을 공유하는 것이므로 이전의 process가 가진 mm_struct를 가지게 되고 mm_strcut의 구조체 포인터를 하나 증가시켜준다. NULL이 아닐 경우에는 수행 되던 process와 주소공간이 다른 것이므로 이 process가 가지고 있던 switch_mm이라는 함수를 호출한다. 여기서 switch_mm이 하는 일은 process의 주소 공간을 교체하는 것이다. 만약 수행중인 process(prev) mm NULL이라면 다른 누군가와 주소공간을 공유하고 있다는 뜻이다. 주소공간을 공유하더라도 이제 실행되지 않으면 active_mm NULL값을 주어 실행되지 않는 process임을 나타낸다. 그리고 runqueue prev_mm에 수행되던 process active_mm을 저장해 두었던 oldmm값을 넣는다. 이러한 주소공간 switching이 모두 일어난 후에 switch_to라는 매크로를 호출하여 레지스터의 저장과 저장되어있던 레지스터를 불러오는 일을 한다.

 

/usr/src/linux-2.4.20-8/include/asm-i386/system.h

 

#define switch_to(prev, next, last) do{

           asm volatile(“pushl %%esi\n\t”

“pushl %%edi\n\t”

“pushl %%ebp\n\t”  //레지스터 값 저장

“movl %%esp,%0\n\t”       /* save ESP */

                                “movl %2,%%esp\n\t”    /* restore ESP */

                                “movl $1f,%1\n\t”           /* save EIP */

                                “pushl %3\n\t”                /* restore EIP */

                                “jmp __switch_to\n”          //__switch_to로 점프

                                “1:\t”

                                “popl %%ebp\n\t”

                              “popl %%edi\n\t”

                                “popl %%esi\n\t”  //레지스터 값 로딩

                                :”=m” (prev->thread.esp), “=m” (prev->thread.eip)//출력

                                :”m” (next->thread.exp),”m”(next->thread.eip),                                                “a”(prev), “d” (next)); //입력

}while(0)

 

 이 부분은 CPU dependent한 부분이므로 CPU에 따라 달라질 수 있다. 이 매크로가 하는 일은 현재 실행중인 프로세서의 레지스터들을 저장하고 스케줄링 되어 실행 될 프로세서의 레지스터들을 가지고 오는 것이다. 먼저 실행중인 프로세서의 레지스터들을 stack에 저장하는데 그것이 esi, ebp, esp이다. thread_struct라는 struct 0번째는 esp0가 있는데 이곳에 esp를 저장하고 2번째에 있는 esp값을 esp에 가져다 놓는다. 그리고 1번째에는 eip가 있는데 이 곳에 1f를 저장하여 다음번에 1f라는 곳에서부터 수행할 것을 알려준다. 3번째 값은 fs인데 이곳에 eip를 저장한다. 그리고 나서 __switch_to로 점프뛰는데 이 함수가 실행되고 난 후에는 바뀐 프로세서가 수행될 것이다. context switch가 완전히 다 일어나고 난 후에는 1: 이라고 되있는 leble부터 스케줄링 된 프로세스가 수행된다. 그래서 ebp, edi, esi가 차례대로 복구된다. m은 메모리를 의미하는데 “=”이 출력을, a 또는 d eax, edx레지스터를 뜻한다. 그래서 밑의 3줄 소스를 보면 prev(현재 실행중인 프로세스) eax레지스터에 저장되고 next(스케줄링 받은 프로세스) edx에 저장이 된다.

 

/usr/src/linux-2.4.20-8/arch/i386/kernel/process.c

 

void __switch_to(struct task_struct *prev_p, struct task_struct *next_p)

{

         struct thread_struct *prev = &prev_p->thread,

*next = &next_p->thread;

           int cpu = smp_processor_id();

           struct tss_struct *tss = init_tss + cpu;

           //현재 실행중인 프로세스 prev FPU상태를 저장

 

           /* never put a printk in __switch_to printk() calls wake_up*() indire ctly*/

 

           unlazy_fpu(prev_p);

 

           /* Reload esp0, LDT and the page table pointer: */

           tss->esp0 = next0->esp0;

           //스케줄링 받은 프로세스next esp0(커널 스택 주소)를 저장

 

           /* Load the per-thread Thread-Local Storage descriptor. */

           load_TLS(next, cpu);

 

           /* Save away %fs and %gs. No need to save %es and %ds, as

         those are always kernel segments while inside the kernel. */

           asm volatile(“movl %%fs, %0”: “=m” (*(int *)&prev->fs));

           asm volatile(“movl %%gs, %0”: “=m” (*(int *)&prev->gs));

           //prev 프로세스의 fs gs레지스터 저장

 

           /* Restore %fs and %gs if needed. */

           if(unlikely(prev->fs | prev->gs | next->fs | next->gs)){

                     loadsegment(fs, next->fs);

                     loadsegment(gs, next->gs);

           } //next 프로세스의 fs gs 레지스터 저장

 

           /* Now maybe reload the debug registers */

           if(unlikely(next->debugreg[7])) {

                     loaddebug(next, 0);

                     loaddebug(next, 1);

                     loaddebug(next, 2);

                     loaddebug(next, 3);

                     /* no 4 and 5 */

                     loaddebug(next, 6);

                     loaddebug(next, 7);

           } //디버그 레지스터 로딩

 

           if (unlikely(prev->ioperm || next->ioperm))

           //IOperm시스템 콜일 경우에만 해당.

{

                     if(next->ioperm) {

                                memcpy(tss->io_bitmap, next->io_bitmap,

IO_BITMAP_SIZE*sizeof(unsigned long));

                                tss->bitmap = IO_BITMAP_OFFSET;

                     } else

                                tss->bitmap = INVALID_IO_BITMAP_OFFSET;

           }

}

 

   이 함수가 처음 하는 일은 현재 실행중인 프로세스의 상태를 저장하는 것이다. 그리고 스케줄링 받은 프로세서의 커널 스택 주소를 저장하는데 이 주소는 tss_struct라는 구조체의 esp0필드에 저장되어야 한다. 이 곳에서 CPU가 사용하는 커널 스택 주소가 결정되기 때문이다. 그 후에는 현재 수행중인 프로세스의 fs, gs 레지스터를 저장한다. fs gs는 데이터 이동시 사용자 세그먼트와 커널 세그먼트를 전환하는데 사용한다. 현재 수행중인 프로세스의 레지스터를 저장한 후에 할일은 당연히 다음 수행 될 프로세스의 레지스터를 로딩하는 것이다. 그리하여 fs, gs 레지스터를 로딩시키고 마지막으로 디버그 레지스터들을 로딩시킨다. 만약 프로세스가 IOperm시스템콜을 호출하였다면 그 프로세스가 I/O bitmap을 가지고 있는지 아닌지를 검사한다. 다음 수행될 프로세스가 I/O bitmap을 가지고 있다면 tss unsigned long크기만큼의 byte를 복사하고 그렇지 않다면 port 제어 명령어를 사용할 수 없다는 플래그를 설정한다.

2007년 11월 22일 목요일

proc, module programing



<< proc file system >>

proc file system은 파일과 프로세스를 통합하여 관리한다.
/proc 디렉토리에 가보면 프로세스나 하드웨어 정보를 담고있는 파일들을 볼 수가 있다.
이 파일들은 실제로 하드디스크 공간을 차지하지는 않으며, 사용자가 접근을 할 때 커널이 그 내용을 동적으로 만들어준다.

즉, user가 proc file system의 내용을 사용하려고 호출을 하면 커널이 그에 맞는 등록함수를 찾아서 사용할 수 있는 것있다.
그러므로 실제 data가 있는 것이 아니고 이 file system을 거쳐서 등록함수를 찾아내는 것이다. 이 등록함수들을 통하여 커널에 접근을 할 수 있으며, 이 함수들을 module이라고 한다.
결국, proc file system은 매개체의 역할을 하는 한마디로 trigger라고 할 수 있다.


그럼, 지금부터 module을 만들어서 proc을 사용해보도록 하자.



<< Module Programing >>

* 주의할 점 *
module programing은 kernel단의 programing이므로 자칫 잘못하다가는 시스템이 죽을 수 있으며, programing을 할 때 평소 사용하던 standard library는 사용할 수 없다.


1. 모듈 init 함수와 exit 함수.

module program에 꼭 필요한 것이 있는데 바로 init함수와 exit함수이다.
init함수는 module이 생성될 때 호출되는 것이며, exit함수는 module이 사라질 때 호출되는 것으로 C++의 생성자/소멸자와 비슷한 개념이다.

함수의 이름은 다음과 같이 지정해주어야만, init함수/exit함수로 인지할 수 있다.

//init 함수
int init_module(void)
{
  
  // ... 필요한 일들을 수행
  
  return 0;
}

//exit 함수
void cleanup_module(void)
{
  // ... 필요한 일들을 수행
}

만약, 원하는 함수이름으로 지정을 하고 싶다면 원하는 이름으로 하되, 그 함수가 init함수/exit함수라는 것을 알려줄 수 있어야 한다.

init함수/exit함수를 지정해주는 매크로는 다음과 같다.
만약 init함수를 int myproc_init(void) 라고 선언하였고, exit함수를 void myproc_exit(void)라고 선언하였다면,

module_init(myproc_init);
module_exit(myproc_exit);


.. 이라고 사용한다.

init함수/exit함수만 알아도 hello world같은 쉬운 프로그래밍을 구현할 수 있다.


2. directory 만들기

내가 만든 모듈을 proc file system에 연결시켜서 사용하기 위해서는 proc file system에 directory가 필요하다.
이 directory로 접근을 하는 명령을 사용한다면 현재 programing하는 module을 가져올 것이다.

보통, directory는 init함수 안에서 생성하게 된다.

directory를 만들기 위해서는 proc_dir_entry라는 구조체가 필요하다.
전역변수로 struct proc_dir_entry형 변수를 하나 pointer로 선언한 후 함수를 호출한다.

static struct proc_dir_entry *dir; //전역변수로 선언
dir = proc_mkdir(MODULE_NAME, NULL);

여기서 말하는 MODULE_NAME은 스스로 지정해주어야 하는 문자열이며, 이 이름으로 directory를 생성한다.
directory생성에 실패할 경우 dir에 NULL값이 retrun되므로 확인하여 에러처리 할 수 있다.


3. read/write 콜백 함수

user가 read나 write를 위하여 module에 접근할 경우 read를 담당하는 함수와 write를 담당하는 함수가 필요하다.
사용자의 요구를 처리하기 위한 함수로 "cat"같은 명령어로 접근할 경우에는 read를 담당하는 콜백함수가 호출되고 "echo"같은 명령어로 접근할 경우에는 write를 담당하는 콜백함수가 호출된다.

그러니까, 결국은 콜백함수를 만들어 줘야 한다는 것이다.
읽기함수나 쓰기 함수의 이름은 어떤 것으로 해주어도 상관이 없지만 형식은 지켜주어야 한다.

읽기/쓰기 call back 함수의 형식은 다음과 같다.

int read_func(char* page, char** start, off_t off, int count, int* eof, void* data);
int write_func(struct file* file, const char *buffer, unsigned long count, void *data);

읽기 함수에서는 읽을 내용을 page에 읽어오고, 쓰기 함수에서는 buffer에 사용자가 쓴 데이터를 가져온다.
이러한 형식으로 선언된 call back함수에서는 read/write로 접근하였을 때 해주어야 할일을 구현하면 된다.

이 call back함수들을 위한 entry를 생성하고 등록을 시켜주는 일은 init함수에서 한다.

우선, READ를 위한 것 부터 보면 다음과 같다.

static struct proc_dir_entry *read_file; //전역변수로 선언
read_file = create_proc_read_entry("read", 0444, "MyProc", myproc_read, NULL);

init함수에서 create_proc_read_entry함수를 호출하여 entry생성과 등록을 시켜준다. 읽기 전용으로 "read"파일을 MyProc 디렉토리 안에 만드는 것이다. 이 때 MyProc은 위에서 생성한 directory (MODULE_NAME)와 이름이 같아야 한다. 0444는 접근 권한이며 myproc_read라는 함수를 call back함수로 등록시켜준다.
create_proc_read_entry라는 함수는 wrapper함수이다. 이 함수 안에서도 결국 create_proc_entry를 호출을 하여 사용하지만 읽기 전용 proc파일을 생성하기 쉽게 하기 위해서 사용한다.
이 wrapper함수도 위에 directory 생성 함수와 마찬가지로 read_file로 return된 값이 NULL이라면 entry생성에 실패한 것이므로 에러처리를 해줄 수 있다.

다음은 WRITE를 위한 함수를 보자.

static struct proc_dir_entry *write_file; //전역변수로 선언
write_file = create_proc_entry("write", 0644, "MyProc");

init함수에서 create_proc_entry를 호출하여 entry를 생성하고 등록시킨다.
읽기/쓰기 전용으로 "write"파일을 MyProc디렉토리 안에 만들게 된다.
create_proc_read_entry 안에서도 이 함수를 호출하게 되나 wrapper함수를 사용하면 더 좋은 점은 읽기전용에 대한 설정들을 자동으로 해준다는 것이다.
create_proc_entry를 호출하게 되면 proc_dir_entry 구조체에 있는 값들을 설정을 해주어야 한다. wrapper함수를 사용하면 call back함수를 자동으로 연결시켜주지만, 이 함수는 그렇지 못하므로 그 연결을 해주기 위한 설정이 필요한 것이다.

write_file->read_proc = proc_read;
write_file->write_proc = proc_write;
//call back함수를 연결해 주어야 한다.


4. 몇 가지 유의 사항

proc_dir_entry 구조체를 생성할 때 성공적으로 만들어지지 못하면 NULL값이 return되므로 에러처리를 해준다.

proc_dir_entry 구조체를 성공적으로 생성한 후에는 구조체에 있는 owner의 값에 THIS_MODULE을 넣어주어야 제대로 동작한다.
즉, 위에 write_file을 예로 들면,
write_file->owner = THIS_MODULE 이런식으로 해주어야 한다.

init함수와 read/write call back함수에는 반드시 return값이 필요하다. 성공을 했을 경우에는 return 0를 해주자.
read/write함수에서는 데이타의 길이를 return하는 경우도 있다.


5. 모듈 컴파일

call back함수와 init/exit함수를 다 구현하였다면 컴파일을 해보자.
2.4커널 버전을 사용한다면 간단한 컴파일 명령으로 컴파일이 가능하다.

$ gcc -c -D__KERNEL__ -DMODULE -O test.c

그러나, 2.6버전의 커널을 사용한다면 Makefile이 반드시 필요하다.

$ vi Makefile

Makefile을 만들어보자.

obj-m := test.o //object file 이름이다.
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
  $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
  rm -rf *.ko
  rm -rf *.mod
  rm -rf *.o
  rm -rf *.cmd

.. 이것이 간단한 Makefile이다.

그리고 나서 컴파일을 하면 여러개의 파일이 마구 생긴다.
그 중에서 우리가 필요한 파일은 test.ko파일이다. (2.4커널버전에서는 test.o)
이것이 바로 module파일이다.


6. module 생성

$ lsmod

.. 라고 명령어를 실행시키면 지금 올라와 있는 module들이 보여진다.
이 곳에 만들어 놓은 module을 올려보자.

$ insmod test.ko

.. 이렇게 하면 만들어 놓은 test라는 이름으로 module이 올라가면서 /proc 아래에 프로그래밍 할 때 MODULE_NAME으로 주어진 이름으로 directory가 하나 생성된다.

$ cat /proc/MyProc/read

.. 라고 하면 read파일에 읽기로 접근한다.

$ echo "test" > /proc/MyProc/write

.. 라고 하면 write파일에 쓰기로 접근한다.

하는일은 call back함수에서 지정한 일을 하게 된다.

module을 삭제하고 싶으면 다음 명령어를 실행시킨다.

$ rmmod test

2007년 11월 15일 목요일

tftp 설치

1. install
  우선, tftp 패키지를 인스톨 해야한다.

  $ yum install tftp-server

  인스톨이 되면서 tftp가 깔리는 동시에 루트에 tftproot 폴더가 생성된다.


2. 설정
  /etc/xinetd.d/ 에 가보면 tftp라는 파일이 있다.
  그 파일을 열어보면 tftp에 대한 설정이 저장되어 있는데 처음 install을 했을 경우, tftp service가 disable되어있다. 그것을 "no"로 바꿔주면 enable된다.


3. 재시작
   $ /sbin/service xinetd restart

  설정을 변경해주었으므로 재시작 한다.


4. 테스트하기
   잘 설치되었는지 보려면 테스트를 해본다.
   $ tftp localhost
   라고 입력하면 자기 컴퓨터의 tftp server로 접속하게 된다.
   기본적으로 루트에 생성된 tftproot폴더로 접속된다. 아무 파일이나 다운받아보자.
   tftp> get test.txt (물론 파일을 다운받으려면 그 폴더에 이 파일이 있어야한다.)
   tftp> quit

   quit한 뒤 현재 폴더에 다운로드 받은 파일이 있나 확인해본다.
   잘 다운받아졌다면, tftp설치 complete!!

2007년 11월 13일 화요일

samba server 사용



samba server에 user추가

samba server에 user를 추가하기 위해서는 일단 리눅스 계정이 있어야만 한다.
그러므로 리눅스 계정이 있다면 그 계정으로 samba server를 만들면 되고, 아니면 리눅스 계정부터 만들어 주어야한다.

$ useradd test

test라는 이름으로 linux계정을 만드는 명령어 이다. 그리고 password를 지정해주어야 하는데 다음과 같다.

$ passwd test

test라는 계정에 password를 지정해줄 수 있게 한다.
passwd는 확인을 하기위해서 두번을 입력받아 저장한다.

이제 samba server에 이 test라는 녀석을 user로 추가해보자.
예전 버전에서는 smbadduser라는 명령어를 썼다고 하던데, 최신버전에서는 그냥 하면 되더라......;;;;;

$ smbpasswd -a test

라고 하면 test라는 계정을 samba server에 추가하면서 passwd설정까지 같이 해주는 것이다. 옵션에 따라서 추가인지 삭제인지 혹은 그룹을 지정하는 것 까지 가능하다.
이 명령어를 사용하면 test라는 계정을 samba server에 추가하면서 samba server에서 사용할 password를 물어본다.
이 때도 마찬가지로 password를 두 번 입력받아 저장한다.

"Added user test." 라는 문구가 뜨면 성공이다.


samba server 접속

server에 접속을 하기 위해서는 smbclient가 필요한데, 없으면 깔아야 한다.

$ yum install samba-client

하면 install이 되고 samba-client가 깔린다.
그리고 samba server에 접속한다.

$ smbclient //IP주소/homeDir -U ID

이런식으로 사용한다.
예를들어 127.0.0.1에 접속하려 하고 내 계정이 test라면,
$ smbclient //127.0.0.1/test -U test 라고 사용한다.
password를 치고 접속을 하면 자신의 directory가 보인다.

프롬프트도 바뀌는데
smb: \>
이렇게 뜬다.
이 samba server에서 받고 싶은 파일이 있다면 get명령어를 사용해서 파일을 받으면 된다.

smb: \> get test.txt

samba server에서 사용할수 있는 모든 명령어는 ?를 치면 다 나온다.

smb: \> ?







2007년 10월 25일 목요일

커널 컴파일



1. 커널 다운로드 받기


$ ftp ftp.kernel.org

login은 anonymous로 한다.

ftp> mget (받을 파일이름)

ftp> quit


현재 폴더에 커널이 받아진 걸 볼 수 있다.

그걸 /usr/src/ 로 옮겨서 압축을 해제한다.

$ tar xvf (파일이름)





2. 커널 컴파일


$cd /usr/src/linux-버전


$ make mrproper

$ make menuconfig

커널 옵션 설정. 필요한것들만 바꾼다.


$ make dep

$ make bzImage

$ make module

크로스 컴파일러 설치

 

리눅스환경에서 arm 기반 프로그램을 컴파일해서 올리자면, arm용 (arm9기반이니까) 컴파일러가 필요한데-

이 때 해야하는 작업이 크로스 컴파일이다.


크로스컴파일. 말은 그럴싸하니 멋있지만, 삽질의 장본인이다. (그앙!)


그럼 우선, 크로스컴파일을 해보자.



<< 크로스컴파일러 깔기 >>

 

1. 다운받는다.


어디서고 상관없지만, 나는 arm.linux.org.uk에서 받았다...

$ wget http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/cross-3.2.tar.bz2

arm용으로 3.2버전을 받았다.


압축을 풀고, 원하는 곳으로 옮긴다.

압축을 풀면 나오는 arm이라는 폴더를 /usr/local/ 에 두었다. (그냥 내맘-_-)


2. 패스설정한다.


그리고 나서 .bash_profile을 고쳐주어야 한다. 그렇지 않으면 command를 찾지 못할 것이다.

.bash_profile은 ~/ 경로를 찾으면 있다.

다른 방법으로 cd 치고 엔터를 누르면 이동하는 경로이다.

보통 ls로는 보이지 않는 파일이고, 파일목록으로 보고 싶으면 ls -al을 하면 보인다.


vi를 이용해서 편집을 한다.

PATH 라고 되어 있는 부분을 찾는다.

보통은

PATH=$PATH:$HOME/bin 이라고 되있을 건데, 여기다가 크로스컴파일러 깐 곳의 path를 입력해준다.

PATH=/usr/local/arm/bin:$PATH:$HOME/bin


bin폴더 아래에 가보면 크로스 컴파일러가 가득한 것을 볼 수 있다.

크로스 컴파일러가 있는 경로를 넣어주면 되는 것이다.


마지막으로 바뀐 bash_profile을 적용시켜주어야 한다.

$ source .bash_profile


그리고 나서 확인을 해보려면, command를 입력해보면 된다.

arm-linux-gcc 라고 입력하고 엔터를 쳤을 때,

input file이 없다고 에러메세지가 뜨면 제대로 경로를 잡은 것이고,

그렇지 않고 없는 command라고 뜬다면 제대로 경로를 잡지 못한것이다.