Operating System note

짱J·2022년 10월 12일
1

오퍼레이팅시스템

목록 보기
1/2
post-thumbnail

🗃 각종 파일 위치

  • /init/main.c
    • start_kernel(),
  • /arch/x86/kernel/Entry_32.S
  • arch/x86/kernel/syscall_table_32.S → sys_call_table
  • /kernel/fork.c
  • /drivers/input/keyboard/atkbd.c → 키보드 입력 관련
    • atkbd_interrupt()

🎨 각종 함수의 위치 및 기능

  • trap_init()
    • arch/x86/kernel/traps_32.c에 정의됨 (리눅스가 32비트 운영체제이기 때문에 64비트 정의는 보지 않는다)
    • 시스템콜을 위한 초기화 작업
  • init_IRQ()
    • arch/x86/kernel/i8259_32.c에 정의됨
    • 인터럽트 설정을 하고, 인터럽트를 동작시킴
  • sched_init()
    • kernel/sched.c에 정의됨
    • init 테스크가 사용하는 CPU 번호를 할당하고, pid hash table을 초기화
    • 타이머 인터럽트 벡터를 초기화
  • time_init()
    • arch/x86/kernel/time_32.c에 정의됨
    • 현재 시간에 대한 정보 제공
  • console_init()
    • drivers/char/tty_io.c에 정의됨
    • 콘솔을 사용하기 위한 시리얼 장치를 초기화
  • mem_init()
    • arch/x86/mm/init_32.c에 정의됨
    • 사용 가능한 메모리를 초기화
  • rest_init()
    • init/main.c에서 정의됨
    • kernel_thread() 함수롤 호출해서 별도의 스레드를 만들고 kernel_init() 함수 수행
    • 자기 자신은 계속 코드를 수행하면서 cpu_idle()를 수행하여 idle process가 됨
  • init_timers()
    • kernel/time.c에 정의됨
  • atkbd_interrupt()
    • 입력 관련 코드 작성할 때

♻️ 코드 변경사항 반영 및 재부팅

make bzImage
cp arch/x86/root/bzImage /boot/bzImage
reboot

💊 출력 로그 레벨 변경

echo 8 > /proc/sys/kernel/printk

🖨 키보드 스캔 코드 표

https://kkamagui.tistory.com/m/476

🌵 Week 1 - Kernel Reading

함수의 위치 찾기

grep -nr "start_kernel" * | more
  • start_kernel()은 main.c에 있음

start_kernel()의 첫 message

  • start_kernel()에는 printk(linux_banner);가 있음
    • linux_banner[]은 /init/version.c에 있음
      • UTS_RELEASE에 리눅스 버전 저장되어 있음 → grep 명령어로 찾을 수 있음(2.6.25.10)

printf 대신 printk를 쓰는 이유

  • 리눅스 커널이 대부분 c언어로 작성되어 있지만 라이브러리를 사용하지 못한다. 커널 이미지 내에 포함된 함수들만 사용할 수 있기 때문에 printf 대신 printk를 사용한다.

🌵 Week 2 - Kernel Compile

첫 프로그램이 실행될 때 위치

  • 0xFFFFFFF0

GRUB(boot loader program)의 위치

  • 부트 디스크의 첫 번째 디스크

리눅스 실행 파일 위치

  • 실행 파일: /boot/bzImage
  • GRUB은 /boot/grub/grub.conf에서 파일 경로를 찾아냄

부팅 로그에 문구 출력

  • init/main.cstart_kernel()printk() 추가
  • 그 후, dmesg > x를 통해 확인

새로운 운영체제 만들기

  • /boot/grub/grub.conf에 아래 코드 추가
title=My Linux3
root (hd0,0)
kernel /boot/bzImage3 root=/dev/ram0 init=/linuxrc ramdisk=8192 real_root=/dev/initrd /initramfs-genkernel-x86-2.6.23-gentoo-r8

유저 로그인 입력을 기다릴 때 CPU의 위치

  • start_kernel() 마지막에 rest_init()을 호출
  • rest_init()에서 cpu_idle() 호출 → /arch/x86/kernel/process_32.c에 있음
    • while(1) 안에서 무한 루프를 돌며 아이디 입력을 기다리고 있음

즉, CPU는 boot sequence에서 start_kernel()을 호출하고 항상 어딘가에서 실행을 하고 있음

🌵 Week 3 - Interrupt

interrupt number

  • A packet has arrived: 42
  • An application program calls scanf(): Interrupt number 128, system call number 3
  • A key is pressed Keyboard: 33
  • An application causes a divide-by-zero error: 0
  • An application program calls printf(): Interrupt number 128, system call number 4
  • An application causes a page-fault error: 14

키보드 입력해도 아무것도 안 뜨도록

static ireqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags) {
	return IRQ_HANDLED;
    ...
}
  • /drivers/input/keyboard/atkbd.c의 atkbd_interrupt() 첫 줄에 return IRQ_HANDLED; 추가
  • 인터럽트가 발생하면 키보드 입력을 처리하고 IRQ_HANDLED를 반환해야 함
    • 하지만 아무런 처리 없이 바로 IRQ_HANDLED를 반환하여 문자 입력이 처리되지 않음

키를 입력하면 "x pressed"가 뜨도록

static ireqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags) {
	struct atkbd *atkbd = atkbd->dev;
    struct input_dev *dev = atkbd->dev;
    unsigned int code = data;
    printk("%x pressed\n", code);
    int scroll=0, hscroll=0, click=-1;
    int value;
    unsigned char keycode;'
    ...
}
  • code 변수를 선언해주는 아래 printk 작성

입력하는 키의 다음 글자가 출력되도록 (root → tppy)

static ireqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags) {
	struct atkbd *atkbd = atkbd->dev;
    struct input_dev *dev = atkbd->dev;
    unsigned int code = data+1;
    int scroll=0, hscroll=0, click=-1;
    int value;
    unsigned char keycode;'
    ...
}
  • code = data + 1

mydelay() : 's' 입력 전까지 booting process 멈춤

  • init/main.c
  • exit_mydelay=0으로 초기화하고, exit_mydelay가 1이 되면 무한 루프를 벗어남
int exit_mydelay;
void mydelay(char *str) {
	printk(str);
    printk("enter s to continue\n");
    exit_mydelay=0; // init to zero
    for(;;) {
    	msleep(1); // sleep 1 micro-second so that keyboard interrupt ISR can do its job
        if(exit_mydelay==1) break; // if user press 's', break
    }
  • kernel_init() 함수 내에 do_basic_setup() 함수 다음에 mydelay 함수 호출
    • do_basic_setup() 전에는 운영체제가 키보드, 마우스, 디스크와 같은 디바이스들과 상호작용을 할 수 없기 때문에 키보드 입력이 되지 않는다.
// kernel_init() 함수 내부
...

do_basic_setup();
mydelay("after do_basic_setup in kernel_init\n");

...
  • /drivers/input/keyboard/atkbd.c
  • atkbd_interrupt()에서 's'가 입력되면 exit_mydelay가 1이 되도록
static ireqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data, unsigned int flags) {
	struct atkbd *atkbd = atkbd->dev;
    struct input_dev *dev = atkbd->dev;
    unsigned int code = data;
    if(code == 31) exit_mydelay=1;
    ...
}

atkbd_interrupt()의 function call

atkbd_interrupt()input_event()input_handle_event()input_pass_to_handlers()handle->handler->event()

🌵 Week 4 - System Call Interrupt

sys_call_table[] 위치

  • /arch/x86/kernel/syscall_table_32.S

length 17 string found

  • fs/read_write.c
asmlinkage ssize_t sys_write(unsigned int fd, const char __user *buf, size_t count) {
	struct file *file;
    ssize_t ret = -EBAF;
    int fput_needed;
    
    if (count == 17) {
    	printk("lenght 17 string found\n");
    }
    
    ...
}
  • mid/ex1.c
#include <stdio.h>

int main() {
	printf("it is 17 long ha\n");
	return 0;
}

syscall 사용 예제

#include <stdio.h>

int main() {
	syscall(4, 1, "hello", 5);
	return 0;
}
  • write(1, "hi", 2) = syscall(4, 1, "hi", 2)
  • 마지막 인자는 문자열의 길이

새로운 시스템 콜 함수

1) arch/x86/kernel/syscall_table_32.S에서 시스템 콜 번호를 만든다.
2) fs/read_write.c에서 sys_write 위에 함수를 정의

asmlinkage void my_sys_call() {
		// ~~~
}

3) 재부팅하고 예제 코드 실행 (예제에서 syscall 함수 호출)

🌵 Week 5, 6 - Process

ps -ef

  • 실행중인 프로세스 목록 출력

display_process()

  • init/main.c 첫 부분에 정의되어 있음
  • 무한루프를 돌면서 init_task부터 연결된 프로세스들을 출력
  • 마지막 프로세스는 다시 init_task를 가리킴

1) start_kernel() 시작 부분에 호출
: 프로세스 1개
2) rest_init() 시작 부분에 호출
: 프로세스 2개
3) kernel_init() 시작 부분에 호출
: 프로세스 3개
4) do_basic_setup() 이후에 호출
: 프로세스 가장 많음

시스템의 모든 프로세스를 출력하는 시스템 콜 함수

  • fs/read_write.c
asmlinkage void my_sys_display_process() {
	struct task_struct *temp;
    temp = &init_task;
    for(;;) {
    	printk("pid: %d, name: %s, state: %ld\n", temp->pid, temp->comm, temp->state);
        temp = next_task(temp);
        if(temp == &init_task) break;
    }
    printk("\n");
}
  • arch/x86/kernel/syscall_table_32.S에서 시스템 번호 추가

  • 예제 코드

#include <stdio.h>

int main() {
	syscall(44);
    return 0;
}

모든 조상 프로세스를 출력하는 시스템 콜 함수

asmlinkage void my_sys_display_process() {
	struct task_struct *temp;
    for(temp=current;temp!=&init_task;temp=temp->parent) {
    	printk("pid: %d, ppid: %d, name: %s, state: %ld\n", temp->pid, temp->parent->pid, temp->comm, temp->state);
        temp = next_task(temp);
        if(temp == &init_task) break;
    }
    printk("\n");
}

pthread

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *foo(void *aa) {
	printf("hello from child\n");
    return NULL;
}

int main() {
	pthread_t x;
    pthread_create(&x, NULL, foo, NULL);
    printf("hi from parent\n");
	return 0;
}
gcc -o ex7 ex7.c -lpthread
  • fork() - child와 parent가 다른 메모리 공간 사용
  • pthread_create() - child와 parent가 같은 body 공유

rest_init() 뒤에 printk() 출력 안되는 이유

rest_init()에서는 마지막에 cpu_idle()을 호출한다.
cpu_idle()은 무한루프를 돌기 때문에
rest_init() 뒤에 printk()를 해도 출력이 되지 않는다.

🌵 Week 7 - IPC

  • fork로 새로운 프로세스를 만들면 프로세스 간의 변수를 공유하지 않고 새로운 메모리를 할당받음
    → race condition X
  • 스레드를 만들면 프로세스 간 일부 변수를 공유함
    • 스레드에서 동시에 한 변수를 읽고 수정하여 race condition이 발생
  • pthread_mutex_lock()을 이용하여 여러 스레드가 동시에 한 변수에 접근하지 못하도록 함
  • 데드락 발생 → 어떤 스레드도 두 변수를 모두 가질 수 없어 계속 대기 상태
    • 사용할 변수에만 락을 해준 뒤, 사용이 끝나면 바로 락을 해주고 다음 락을 해주고 해제해줌
int main() {
	pthread_mutex_init(&lock, NULL);
    pthread_create(&t1, NULL, &foo1, NULL);
    pthread_create(&t2, NULL, &foo2, NULL);
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    pthread_mutex_destroy(&lock);

	return 0;
}
profile
[~2023.04] 블로그 이전했습니다 ㅎㅎ https://leeeeeyeon-dev.tistory.com/

0개의 댓글