시스템 콜 이해하기 - 4.구조체를 사용한 인자 전달
앞의 문서의 내용에서 좀더 확장되는 것으로 구조체를 이용한 인자전달에 대해서 알아볼 것이다.
시스템 콜 작성하기
먼저 unistd.h 파일에 다음을 추가한다.
#define __NR_getstat 262
entry.S 파일에 다음을 추가한다.
.long SYMBOL_NAME(sys_ni_syscall) /* sys_set_tid_address */
.long SYMBOL_NAME(sys_newsyscall) /* sys_set_tid_address */
.long SYMBOL_NAME(sys_gettaskinfo) /* sys_set_tid_address */
.long SYMBOL_NAME(sys_show_mult) /* sys_set_tid_address */
.long SYMBOL_NAME(sys_getstat) /* sys_set_tid_address */
.rept NR_syscalls-(.-sys_call_table)/4
.long SYMBOL_NAME(sys_ni_syscall)
.endr
이제 시스템 콜 함수를 작성한다. 파일이름은 각각 mystat.h, getstat.c 이고, kernel 디렉토리 아래에 둔다.
struct mystat {
int pid;
int ppid;
/*
* pid_t pid;
* pid_t ppid;
*/
int state;
int priority;
int policy;
long utime;
long stime;
long starttime;
unsigned long min_flt;
unsigned long maj_flt;
int open_files;};
#include <linux/unistd.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <asm-i386/uaccess.h>
#include "mystat.h"
// #include <linux/malloc.h>
#include <linux/slab.h>
asmlinkage int sys_getstat(int id, struct mystat *user_buf)
{
struct mystat *buf;
int i = 0, cnt = 0;
struct task_struct *search;
search = &init_task;
while(search->pid != id)
{
search = search -> next_task;
if(search->pid == init_task.pid)
return(-1);
}
buf = kmalloc(sizeof(struct mystat), GFP_KERNEL);
if(buf == NULL)
return(-1);
buf->pid = search->pid;
buf->ppid = search->p_pptr->pid;
buf->state = search->state;
buf->priority = search->rt_priority;
buf->policy = search->policy;
buf->utime = search->times.tms_utime;
buf->stime = search->times.tms_stime;
buf->starttime = search->start_time;
buf->min_flt = search->min_flt;
buf->maj_flt = search->maj_flt;
for(i=0; i<256; i++)
if(current->files->fd_array[i] != NULL)
cnt++;
buf->open_files = cnt;
copy_to_user(user_buf, buf, sizeof(struct mystat));
return(0);
}
Makefile 에 getstat.o 를 추가한 후, 커널 컴파일을 해서 새로운 커널 이미지로 부팅한다.
Application 작성하기
파일이름은 test3.c 이고, /root 디렉토리 아래에 저장한다. 이때 앞에서 작성한 mystat.h 파일도 함께 있어야 한다.
#include <linux/unistd.h>
#include <stdio.h>
#include <errno.h>
#include "mystat.h"
struct mystat *mybuf;
_syscall2(int, getstat, int, taskid, struct mystat *, ret_buf);
int main(int argc, int* argv[])
{
int task_number;
if(argc != 2){
printf("USAGE: a.out pid\n");
exit(1);
}
task_number = atoi(argv[1]);
mybuf = (struct mystat *)malloc(sizeof(struct mystat));
if(mybuf == NULL){
printf("Out of Memory\n");
exit(1);
}
getstat(task_number, mybuf);
printf("PID = %d\n", mybuf->pid);
printf("PPID = %d\n", mybuf->ppid);
if(mybuf->state == -1) printf("Unrunable state\n");
else if(mybuf->state == 0) printf("Running state\n");
else if(mybuf->state == 1) printf("Interruptable state\n");
else if(mybuf->state == 2) printf("Uninterruptable state\n");
else if(mybuf->state == 4) printf(" Stopped state\n");
else if(mybuf->state == 8) printf(" Zombie state\n");
else if(mybuf->state == 16) printf(" Dead state\n");
else printf("Unknown state\n");
printf("Priority = %d\n", mybuf->priority);
printf("Policy = %d\n", mybuf->policy);
printf("Task.utime = %lu\n", mybuf->utime);
printf("Task.stime = %lu\n", mybuf->stime);
printf("Task.starttime = %lu\n", mybuf->starttime);
printf("minor fault = %lu\n", mybuf->min_flt);
printf("major fault = %lu\n", mybuf->maj_flt);
printf("opened files = %lu\n", mybuf->open_files);
}
컴파일 후에 실행해보자!
[root@localhost root]# ./a.out 1 PID = 1 PPID = 0 Interruptable state Priority = 0 Policy = 0 Task.utime = 0 Task.stime = 418 Task.starttime = 41 minor fault = 62 major fault = 128 opened files = 42