/init/main.c
/arch/x86/kernel/Entry_32.S
arch/x86/kernel/syscall_table_32.S
→ sys_call_table/kernel/fork.c
/drivers/input/keyboard/atkbd.c
→ 키보드 입력 관련trap_init()
init_IRQ()
sched_init()
time_init()
console_init()
mem_init()
rest_init()
init_timers()
atkbd_interrupt()
make bzImage
cp arch/x86/root/bzImage /boot/bzImage
reboot
echo 8 > /proc/sys/kernel/printk
https://kkamagui.tistory.com/m/476
grep -nr "start_kernel" * | more
main.c
에 있음printk(linux_banner);
가 있음/init/version.c
에 있음UTS_RELEASE
에 리눅스 버전 저장되어 있음 → grep 명령어로 찾을 수 있음(2.6.25.10)/boot/bzImage
/boot/grub/grub.conf
에서 파일 경로를 찾아냄init/main.c
의 start_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는 boot sequence에서 start_kernel()을 호출하고 항상 어딘가에서 실행을 하고 있음
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;
추가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;'
...
}
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;'
...
}
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("after do_basic_setup in kernel_init\n");
...
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()
→ input_event()
→ input_handle_event()
→ input_pass_to_handlers()
→ handle->handler->event()
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");
}
...
}
#include <stdio.h>
int main() {
printf("it is 17 long ha\n");
return 0;
}
#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 함수 호출)
1) start_kernel() 시작 부분에 호출
: 프로세스 1개
2) rest_init() 시작 부분에 호출
: 프로세스 2개
3) kernel_init() 시작 부분에 호출
: 프로세스 3개
4) do_basic_setup() 이후에 호출
: 프로세스 가장 많음
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");
}
#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()에서는 마지막에 cpu_idle()을 호출한다.
cpu_idle()은 무한루프를 돌기 때문에
rest_init() 뒤에 printk()를 해도 출력이 되지 않는다.
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;
}