가상메모리 영역의 정보와 파일의 이름을 출력하려고 합니다
안녕하세요. 반갑습니다.
리눅스를 기초만 공부해보려고 하는데 ... 정말 어렵네요 ㅠㅠ
그래서 사실 왕왕초보입니다.
질문올리기두 창피해서 왠만하면 혼자 찾아보려고 했는데 멍청한짓 같아서요..
지금 제 문제는 이렇습니다.
태스크에 할당된 가상메모리의 정보와 파일이름을 출력해보려고 하는데요
시스템콜을 모듈로 작성하여 테스트하려고합니다.
그런데 모듈을 적재하고, 응용프로그램을 실행하면 Segmentation fault(core dumped) 에러가 뜹니다.
메모리를 잘못사용한거같은데 ...
'리눅스시스템&커널기초:커널분석에서 수정까지' 라는 책의 실습하기6-2를 보고 하는데 이 책이 커널 2.4이전이여서 달라진게 많네요.
제가 사용하는건 리눅스 우분투 16 버전이고, VirtualBox를 사용하고있습니다.
1. 시스템호출 코드
#include <linux/kernel.h> #include <linux/module.h> #include <sys/syscall.h> #include <asm/uaccess h> #include <linux/sched.h> #include <linux/mm.h> #define __NR_getmeminfo 334 asmlinkage int (*saved_entry) (void); void **sys_call_table; asmlinkage int sys_getmeminfo(int pid) { struct task_struct *t; struct mm_struct *mm; struct vm_area_struct *mmap; struct file *file; char *filename; char *buf; t=pid_task(find_vpid(pid), PIDTYPE_PID); if(t == NULL){ printk(“Cannot find PID from user program\n”); return 0; } mm = t->active_mm; mmap = mm->mmap; buf = kmalloc(512, GFP_KERNEL); while(mmap) { printk(“%08lx - %08lx”, mmap->vm_start, mmap->vm_end); file = mmap->vm_file; if(file){ filename = d_path(&file->f_path, buf, 512); printk(“%s \n”, filename); } else { printk(“\n”); { mmap = mmap->vm_next; } return 0; } int module start(void) { saved entry = sys_call_table[__NR_getmeminfo]; sys_call_table[__NR_getmeminfo] = sys_getmeminfo; return 0; } void module_end(void) { sys_call_table[__NR_getmeminfo] = saved_entry; } module_init(module_start); module_exit(module_end); MODULE_LICENSE(“GPL”);
잘은 모르겠지만 여기서 filename = d_path(&file->f_path, buf, 512);
부분이 문제인거같아요.
책에는 filename = d_path(&file->f_path, buf, 512);
라고 나와있지만 커널이 버전업되면서 바뀐것 같더라구요.
그래서 제가 찾은곳은 https://github.com/iamroot11c/kernel/blob/master/mm/memory.c
여기에서 4289 line 입니다. 이걸보고 저렇게 바꿧엇거든요..
뭐가문제일까요?ㅠㅠ 어떻게 해야 할까요. ㅠㅠ
감사합니다.
혹시몰라 응용프로그램 소스코드도 올립니다.
2. 응용프로그램 코드
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<linux/unistd.h> #include<errno.h> #include<sys/syscall.h> #define __NR_getmeminfo 334 int main(int argc, char *argv[]) { int i, pid; pid = atoi(argv[1]); i = syscall(__NR_getmeminfo, pid); return 0; }
컴파일 할 때 gcc -Wall 해 보셔요. 경고
컴파일 할 때 gcc -Wall 해 보셔요. 경고 메시지가 자세히 나올 겁니다. 그걸 보면서 고쳐보셔요.
세벌 https://sebuls.blogspot.kr/
이런 경고 메시지만 나오더라구요..
이런 경고 메시지만 나오더라구요..
그래서 printf로 i를 출력했습니다.
그 이후로 경고메시지는 안나오고 여전히 Segmentation fault가 뜹니다 ㅠㅠ
core dumped가 떴다면 gdb bt (back
core dumped가 떴다면 gdb bt (back trace)로 어디에서 세그멘테이션 오류가 떴는지 알수 있지 않을까요?
gdb 에서 bt를 사용하니 이렇게 나옵니다 ..
gdb 에서 bt를 사용하니 이렇게 나옵니다 .. 근데 제가 보는 방법을 잘 몰라서요 ㅠㅠ
음.. gdb에서 r을 하는게 아니라 coredump
음.. gdb에서 r을 하는게 아니라 coredump 파일을 로드하면서 bt를 해야 하는데요
gdb 실행파일 "core dump file"
그리고 bt
그리고 올려주신 것을 보면 atoi를 부르면서 죽었은 것 같은데요 아마 gdb에서 호출할 때 인자를 빼먹어서 그런 거 같은데 --args 를 넣어서 다시 gdb 호출해 보세요
gdb --args ./getmeminfo 33579
식으로요
buf를 포인터로 하지말고 배열로 선언하고 memset으로 초기화 해보시겠어요?
char buf[512] 이렇게요
혹시 memset으로 해당 오류 해결하셨나요?
*buf로 하면 killed가 뜨고 buf[512]로 하면 세그먼트 펄트 뜨는데 왜이럴까요ㅜㅜ
댓글 달기