본문 바로가기

Studies/Advanced Programming in the UNIX Environment

myShell

입력받은 커맨드를 실행하고, 그 실행 시간을 측정한다. 유닉스 쉘의 입력 부분만 흉내낸 것

Get command from user, then calculate the command's execute time.
This is a simple UNIX shell. Just make command input part
 

#include <sys/types.h> //for types for time and etc.
#include <sys/wait.h>  //for wait()
#include <signal.h>  //for signal catching
#include "ourhdr.h"  //System Programming Default Header
#include <sys/times.h> //for times()

//functions
static void sig_int(int);  /* our signal-catching function */
static void report(void);  // print report
static void pr_times(clock_t, struct tms *, struct tms *); //time checker

//global variable : to save data
char cmd[80][80];
double rtime[80];
double utime[80];
double stime[80];

int num_of_cmd = -1; // counter

// MAIN  //////////////////////////////////////

int main(void)
{
    char buf[MAXLINE];
    pid_t pid;
    int status;
    struct tms tmsstart, tmsend; //structure for time check
    clock_t start, end;   //variable for time

    if (signal(SIGINT, sig_int) == SIG_ERR) //signal checker
    { err_sys("signal error"); }

    printf("%% "); /* print prompt (printf requires %% to print %) */

    while (fgets(buf, MAXLINE, stdin) != NULL)  //^D를 제외한 입력의 경우 : ^D이면 루프 끝
    {
        buf[strlen(buf) - 1] = 0; /* replace newline with null */
        num_of_cmd++; // Counter ++

        if ( (pid = fork()) < 0)
        { err_sys("fork error"); }
        else if (pid == 0)
        {
            /* child */
            execlp(buf, buf, (char *) 0);  //입력받은 커맨드 실행 후 else if 블록을 빠져나감
            // 커맨드가 실행되지 않는 경우
            err_ret("couldn't execute: %s", buf);
            exit(127);
        }

        strcpy (cmd[num_of_cmd], buf);  //입력 받은 커맨드를 전역변수 배열에 저장

        if ( (start = times(&tmsstart)) == -1) /* starting values */
        { err_sys("times error"); }

        /* parent */
        if ( (pid = waitpid(pid, &status, 0)) < 0)
        { err_sys("waitpid error"); }

        if ( (end = times(&tmsend)) == -1)  /* ending values */
        { err_sys("times error"); }

        pr_times(end-start, &tmsstart, &tmsend); //시간 계산
        printf("%% "); //프롬프트 출력
    }

    report(); //^D 입력시 루프 종료 후 결과 표시

    exit(0);
}

void sig_int(int signo) //시그널 입력 시 출력
{
 //printf("interrupt\n%% ");
}

static void pr_times(clock_t real, struct tms *tmsstart, struct tms *tmsend) // 시간 체크
{
    static long clktck = 0;

    if (clktck == 0) /* fetch clock ticks per second first time */
    {
        if ( (clktck = sysconf(_SC_CLK_TCK)) < 0) //시스템 상수를 받아옴
        { err_sys("sysconf error"); }
    }

    // fprintf(stderr, "  real:\t\t%7.2f\n", real / (double) clktck);
    // fprintf(stderr, "  user:\t\t%7.2f\n", (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck);
    // fprintf(stderr, "  system:\t%7.2f\n", (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck);

    rtime[num_of_cmd] = real / (double) clktck; //시간을 계산하여 배열에 저장
    utime[num_of_cmd] = (tmsend->tms_cutime - tmsstart->tms_cutime) / (double) clktck;
    stime[num_of_cmd] = (tmsend->tms_cstime - tmsstart->tms_cstime) / (double) clktck;
}

void report(void)
{
    int loop;

    for (loop = 0; loop <=num_of_cmd; loop++) //전체 시행 시간을 계산, 배열의 마지막에 추가
    {
        strcpy (cmd[num_of_cmd+1], "Total");
        rtime[num_of_cmd+1] += rtime[loop];
        utime[num_of_cmd+1] += utime[loop];
        stime[num_of_cmd+1] += stime[loop];
    }

    // 출력 시작
    printf ("\n\t\tProcess\tSystem time\tUse time\tReal time\n");

    for (loop = 0; loop <=num_of_cmd; loop++)
    {
        if (rtime[loop]==0 && utime[loop]==0 && stime[loop]==0) //커맨드 오류시 모든 시간이 0로 표시됨을 이용, 에러커맨드는 출력하지 않음
        {   /* Do nothing */    }
        else
        {
            fprintf(stderr, "  %s:\t", cmd[loop]);
            fprintf(stderr, "  \t\t%7.2f",rtime[loop]);
            fprintf(stderr, "  \t%7.2f", utime[loop]);
            fprintf(stderr, "  \t%7.2f\n", stime[loop]);
        }
    }

    // total 값 출력
    printf ("-------------------------------------------------------------------\n");
    fprintf(stderr, "  %s:\t", cmd[num_of_cmd+1]);
    fprintf(stderr, "  \t%7.2f",rtime[num_of_cmd+1]);
    fprintf(stderr, "  \t%7.2f", utime[num_of_cmd+1]);
    fprintf(stderr, "  \t%7.2f\n", stime[num_of_cmd+1]);
}

'Studies > Advanced Programming in the UNIX Environment' 카테고리의 다른 글

File mode checker  (0) 2008.08.12
myCAT : cat(1)  (0) 2008.08.12
WC : Word Count  (0) 2008.08.10
실행파일 만들기 : Make a .exe file for APUE  (0) 2008.08.10
error.c  (0) 2008.08.10