앞의 문서의 내용에서 좀더 확장되는 것으로 구조체를 이용한 인자전달에 대해서 알아볼 것이다.

시스템 콜 작성하기

먼저 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
  • computer/embedded/시스템_콜_이해하기_-_4.구조체를_사용한_인자_전달.txt
  • Last modified: 3 years ago
  • by likewind