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 제어 명령어를 사용할 수 없다는 플래그를 설정한다.

2008년 3월 25일 화요일

천일의 스캔들.


천일의 스캔들.

주연: 스칼렛 요한슨(메리 역), 나탈리 포트만(앤 역), 에릭 바나(헨리8세 역)
감독: 저스틴 채드윅


어느 한 시골에 평화롭게 살아가고 있는 앤, 메리, 조지 삼남매.
아버지는 착실한 한 남자에게서 청혼이 들어오자 욕심많은 첫째 앤보다는 메리가 결혼하기를 원하고, 시골에서 조용히 살고싶은 메리는 그와 결혼하려한다.

그러던 중 삼남매의 삼촌이 되는 사람이 궁정에서 나온다.
그는 삼촌이기도 하지만 궁에서 권력을 쥐고 있는 사람으로 현재의 왕비가 더 이상 왕자를 낳지 못하자 앤을 왕에게 바치려 한다.

메리의 결혼식이 있고 얼마 있지 않아서 삼남매의 집으로 왕이 찾아온다.
앤은 왕의 눈에 들려고 노력하지만 왕이 마음에 들어한건 메리로 결국 메리를 궁으로 데리고 간다.

메리는 자신의 마음을 이해해 주는 왕에게 진심으로 반하게 되고, 왕의 아이를 임신하게 되자, 부모님과 삼촌은 큰 권력을 갖게 된다.
그리고 앤은 궁전 생활을 즐기던 중 정혼자가 있는 다른 귀족과 몰래 결혼하게 되는데, 이 사실을 알게 된 메리와 조지는 앤을 걱정하는 마음에 이 사실을 부모님께 말했지만, 크게 혼나고 프랑스로 쫓겨나게 된 앤은 메리에게 복수할 것을 결심한다.

어느 날, 갑자기 쓰러진 메리는 유산의 위기는 넘겼지만 침대 위에 누워서만 지내야 한다는 진단을 받게 되고, 메리의 삼촌은 이 사실을 알게 되자 초조해하며 앤을 다시 부른다.
프랑스에서 돌아온 앤은 예전과는 다른 모습으로 헨리의 마음을 얻어내지만, 도도한척 동생을 핑계로 왕을 밀어내며 왕을 애태운다.
그리고선, 왕의 마음을 빌미로 메리를 버리게 만들고, 왕비를 폐비 시키게 하고, 카톨릭에서 등을 돌리게 한다. 그렇게 얻어낸 왕의 마음과 왕비의 자리. 그러나 앤은 행복하지가 않다.

스포일러 보기



이 영화를 보기전에 '핸리 8세의 여인들'이라는 책을 봤었다.
두 권짜리 책인데 너무 너무 지루해서 끝까지 보지는 못했지만 책에서 봤던 내용이 약간이나마 나와서 이해하면서 볼 수 있었다.ㅎ
아마, 앤 다음 여왕은 '제인 시무어' 였을 것이다.

생각했던 것 만큼 재밌는 영화는 아니었지만, 지루하지 않게 스토리 전개는 빨랐고,
무엇보다 나탈리포드만과 스칼렛요한슨이 이뻤다+_+)
그리고.. 기대했던 베드신은 없었다.. -_-
(닝기미, 포스터에 낚였다..)

2008년 3월 10일 월요일

NetBeans 시작하기


<< NetBeans 시작하기 >>



1. NetBeans 설치

다운로드하기 

위의 링크에서 다운받을 경우, NetBeans와 JDK가 같이 설치되며 JAVA환경변수에 관한 다른 설정이 필요 없게 된다. ^ㅡ^!!


2.
NetBeans에 대해서

NetBeans란,
- JAVA  Application 개발을 위한 platform
- NetBeans platform을 사용해 개발된 IDE
- Modular Architecture

NetBeans platform이란,
- 재사용 가능한 framework로서 다른 desktop application의 개발을 간단하게 해준다
- user interface management등 여러가지 기능을 제공
- 모듈 집합들로 개발된 application을 실행시킬 수 있는 platform

NetBeans IDE란,
- NetBeans platform기반 위에 구성된 플러그인 집합
- Enterprise, desktop, mobile, web programming 등


3. HelloWorld를 출력하기

NetBeans 실행하기

사용자 삽입 이미지

새 프로젝트를 만든다.

[FILE] → [New Project]
사용자 삽입 이미지
Categories에서 JAVA, Projects에서 Java Application을 선택하고 Next!!

사용자 삽입 이미지
Project Name에 원하는 Project이름을 쓴다.
여기에 쓰는 이름은 새로 생성되는 Project 폴더의 이름이 되는 동시에 곧 만들 application의 package이름이 된다.
제일 아래에 Create Main Class를 선택하면 Main Class를 자동적으로 생성해주는데 hello.Main이라고 하면, hello package의 주 class이름이 Main이 된다. class이름을 바꿔주려면 Main인 부분을 바꿔주면 된다.

코딩하기
package hello;
/**
*
* @author Jessical
*/
public class Main{
/**
* @param args the command line arguments
*/
   public static void main(String[] args){
      System.out.println("Hello World!");
   }
}
실행하기
compile: [build] → [build Main Project]
Run: [Run] → [run main project]
사용자 삽입 이미지
실행하면 output창에 Hello World라고 뜬다-_-)z

바보.


바보.

주연: 차태현(승룡이 역), 하지원(지호 역), 박희순(상수 역)
감독: 김정권


강풀 님의 만화를 영화화한 작품이다. 난 개인적으로 강풀의 만화도 좋아하고 차태현의 연기도 좋아하기 때문에 기대를 조금 했었다. (하지원은 별로 좋아하지 않는데 아주 이쁘게 나왔더라+_+ㅎㅎ) 게다가 동생의 바람잡이까지~!

아저씨 냄새 풀풀나는 동기들과 함께 7명이서 영화관으로 향했다. 그리고 바보를 보는데-_-) 뒤에 초딩이 처음부터 참 거슬리더만,, 마지막까지 기분잡치는데 한몫하더라.

난 아주 재밌게 봤는데, 같이본 남자놈들은 하나같이 재미없었다고 하고, 여자애들은 너무 슬프단다. 난 눈물은 안났지만 그래도 좀 찡하긴 했다.


승룡이는 풍납동 사람들이라면 누구나 다 아는 바보이다. 어렸을 때 연탄가스를 마시고 바보가 되어 버렸다. 아버지는 연탄가스 때문에 돌아가시고, 어머니는 지병으로 돌아가셨지만 동생 지인이가 있어서 행복하다. 친구 상수와 돌아온 지호까지 승룡이는 주변에 너무 좋은 사람들이 많다.

지호는 승룡이의 첫사랑이자 마지막 사랑이다. 피아노를 위해서 출국했지만 큰 무대에 서서는 정작 피아노를 칠 수 없었던 자신을 한탄하며 귀국하고는 다시는 피아노를 치지 않는다. 그러나 승룡이로 인해 차차 닫혔던 마음이 열리고 피아노 앞에 앉게 된다.

상수는 어렸을 때부터 문제아 였지만 순수한 승룡이 앞에서 만큼은 허세를 부리고 싶지도, 강한척 하고 싶지도 않다. 하나밖에 없는 친구 승룡이를 위해서 그리고 승룡이의 행복을 위해서 뭐든지 해주고 싶다.

웃으면서 머리에 피를 흘리던 승룡이는 죽는 순간에 행복했을까. 그토록 듣고 싶었던 지호의 피아노 소리를 들으며 눈을 감는다. 그리고 하늘에서는 눈이 아니 별이 내린다.


영화를 보면 풍납동을 아주 잘 그려냈다. 원작에 충실한 영화라고나 할까. 그래서 더더욱 너무 좋았던 영화였다. 영화적 요소를 가미할 만도 한데 김정권 감독은 그러지 않았다. 하지만 결말을 모두 알고 있음에도, 만화와 같은 내용이라서 뒷내용을 예상할 수 있음에도, 이 영화는 좋았다.

멜로영화를 싫어한다면 비추하지만, 간만에 울어보는 것도 좋지 않을까.ㅎㅎ
게다가 이 영화는 예쁘니까.ㅎ