//************************************** // ksamp.c // Kernel Projects for Linux Gary Nutt // p.57-67 // // [History] // 2004/02/20 // とりあえず動作するようになった。 // ブラッシュアップが必要だが、まあ、いいでしょう。 // 2004/02/20 // ポインタの使いかたで混乱 // sleep関数はなんとかクリア // 2004/02/19 // 日本語のコメントがたびたび化けてしまう。 // しばらく、日本語のコメントを控える。 //************************************** #include #include #include #include #define STANDARD 0 #define SHORT 1 #define LONG 2 #define LB_SIZE 256 //------------------------------------- //文字列の左側 n 個の文字列を取り出す left (bstr, astr, an) char *bstr, *astr; int an; { int k; for (k = 0; k < an; k++) *(bstr + k) = *(astr + k); *(bstr + an) = '\0'; } //------------------------------------- //文字列の右側から n 文字を取り出す right (bstr, astr, an) char *bstr, *astr; int an; { int k, al; al = strlen (astr); if (an > al) an = al; for (k = 0; k < an; k++) *(bstr + k) = *(astr + k + al - an); *(bstr + an) = '\0'; } //------------------------------------- //文字列の中から文字列を取り出す //x 番目の文字から n 個の文字を取り出す mid (bstr, astr, ax, an) char *astr, *bstr; int ax, an; { int k; for (k = 0; k < an; k++) { *(bstr + k) = *(astr + k + ax - 1); } *(bstr + an) = '\0'; } //------------------------------------- //文字列の中から任意の文字列を探し //その文字列の位置を与える関数 //存在しなければ0を返す instr (astr, bstr) char *astr, *bstr; { int k, i, j, la, lb, po; la = strlen (astr); lb = strlen (bstr); for (k = 0; k < la - lb + 1; k++) { i = 0; for (j = 0; j < lb; j++) if (*(astr + k + j) == *(bstr + j)) i++; if (i == lb) { po = k + 1; break; } else po = 0; } return (po); } //-------------------------------------- // :でふたつに区切られた文字列を切り分ける separete_by_colon (bstr1, bstr2, astr) char *astr, *bstr1, *bstr2; { if (strlen (astr) > 1) { int pos; pos = instr (astr, ":"); if (pos == 0) { strcpy (bstr1, ""); strcpy (bstr2, ""); } else { left (bstr1, astr, pos - 1); *(bstr1 + pos) = '\0'; if (isspace (*(astr + strlen (astr)))) { mid (bstr2, astr, pos + 1, strlen (astr) - pos - 1); } else { mid (bstr2, astr, pos + 1, strlen (astr) - pos); } *(bstr2 + strlen (bstr2)) = '\0'; } } else { strcpy (bstr1, ""); strcpy (bstr2, ""); } } //-------------------------------------- //コンマで区切られた数値文字列から先頭の数値と、それを除いた数値文字列を返す separete_by_comma (char *head_value, char *remain_value, char *source_value) { // printf("source value = %s\n",source_value); if (!(strchr (source_value, ',') == NULL)) { left (head_value, source_value, (strchr (source_value, ',') - source_value)); right (remain_value, source_value, strlen (source_value) - strlen (head_value) - 1); // printf("source is not empty. head value is %s. remain value is %s\n",head_value,remain_value); } else { strcpy (head_value, source_value); strcpy (remain_value, ""); } //donothing } //-------------------------------------- delete_blank (bstr, astr) char *bstr, *astr; { int i; char a_char[LB_SIZE]; char temp1[LB_SIZE], temp2[LB_SIZE]; if (strlen (astr) > 0) { for (i = 1; i < strlen (astr); i++) { mid (a_char, astr, i, 1); if (*a_char != ' ' || *a_char != '\t' || *a_char != '\n') { mid (temp1, astr, i, strlen (astr) - i + 1); break; } } } if (strlen (temp1) > 0) { for (i = strlen (temp1); i > 0; i--) { mid (a_char, astr, i - 1, 1); if (*a_char != ' ' || *a_char != '\t' || *a_char != '\n') { left (temp2, astr, i - 1); break; } } } strcpy (bstr, temp2); } //------------------------------------- //両端のカッコを取り除く deleteKakko (bstr, astr) char *astr; //source char *bstr; //destination { int i; char a_char[LB_SIZE]; char temp1[LB_SIZE], temp2[LB_SIZE]; if (*astr == '(') { // printf("Kakko( Detected!\n"); mid (temp1, astr, 2, strlen (astr) - 1); } else { strcpy (temp1, astr); } if (*(temp1 + strlen (temp1) - 1) == ')') { // printf("Kakko) Detected!\n"); mid (temp2, temp1, 1, strlen (temp1) - 1); } else { strcpy (temp2, temp1); } strcpy (bstr, temp2); // printf("result is %s\n",bstr); } //-------------------------------------- void doHeader (repTypeName) char repTypeName[16]; { FILE *thisProcFile; char lineBuf[LB_SIZE]; struct timeval now; gettimeofday (&now, NULL); printf ("Status report type %s at %s", repTypeName, ctime (&(now.tv_sec))); thisProcFile = fopen ("/proc/sys/kernel/hostname", "r"); fgets (lineBuf, LB_SIZE + 1, thisProcFile); printf ("Machine hostname; %s", lineBuf); fclose (thisProcFile); } //-------------------------------------- //引数が無かったときの処理 void doStandard () { FILE *thisProcFile; char lineBuf[LB_SIZE]; char cpuType[LB_SIZE]; char cpuModel[LB_SIZE]; char upTime[LB_SIZE]; char value_name[LB_SIZE]; char value_string[LB_SIZE]; thisProcFile = fopen ("/proc/cpuinfo", "r"); while (fgets (lineBuf, LB_SIZE, thisProcFile)) { separete_by_colon (value_name, value_string, lineBuf); if (strcmp (value_name, "") != 0) { delete_blank (value_name, value_name); delete_blank (value_string, value_string); if (!strcmp (value_name, "vendor_id")) { printf ("CPU vendor is %s\n", value_string); } if (!strcmp (value_name, "model name")) { printf ("CPU model is %s\n", value_string); } } else { break; } strcpy (lineBuf, ""); } thisProcFile = fopen ("/proc/uptime", "r"); while (fgets (lineBuf, LB_SIZE, thisProcFile)) { int num; int uptime; int idletime; int sec, min, hour; num = sscanf (lineBuf, "%s %s", value_name, value_string); uptime = (int) atoi (value_name); sec = (int) (uptime) % (60); min = (int) (uptime / (60)) % 60; hour = (int) (uptime / (60 * 60)); printf ("uptime %d , hour %d, min %d, sec %d\n", uptime, hour, min, sec); } } //-------------------------------------- //以下の情報を表示 // CPUがユーザモード、システムモード、アイドルのそれぞれで費やした時間を // /proc/stat から得る // システムに対するディスクI/0要求の数 // カーネルが実行したコンテキストスイッチの回数 // システムの最終起動時刻 // システムを起動してから現在に到るまでに生成されたプロセスの数 void doShort () { FILE *thisProcFile; char lineBuf[LB_SIZE]; int value_num; char temp1[LB_SIZE], temp2[LB_SIZE], temp3[LB_SIZE], temp4[LB_SIZE], temp5[LB_SIZE]; int itemp1, itemp2, itemp3, itemp4, itemp5; thisProcFile = fopen ("/proc/stat", "r"); while (fgets (lineBuf, LB_SIZE, thisProcFile)) { value_num = sscanf (lineBuf, "%s %s %s %s %s", temp1, temp2, temp3, temp4, temp5); // printf("buf is %s, value_num is %d, head val is %s\n",lineBuf,value_num,temp1); if (!strcmp (temp1, "cpu")) { itemp2 = (int) (atoi (temp2) / 100); itemp4 = (int) (atoi (temp4) / 100); itemp5 = (int) (atoi (temp5) / 100); printf ("user mode cpu time %d[sec], system mode cpu time %d[sec], idle cpu time %d[sec]\n", itemp2, itemp4, itemp5); } if (!strcmp (temp1, "disk_io:")) { char temp01[LB_SIZE]; char temp02[LB_SIZE]; char temp03[LB_SIZE]; char temp04[LB_SIZE], temp05[LB_SIZE], temp06[LB_SIZE], temp07[LB_SIZE], temp08[LB_SIZE]; char temp11[LB_SIZE]; char temp12[LB_SIZE]; int disk_io_num; separete_by_colon (temp01, temp02, temp2); // printf("temp01 = %s, temp02 = %s\n",temp01,temp02); deleteKakko (temp03, temp02); // printf("temp03 = %s\n",temp03); separete_by_comma (temp04, temp11, temp03); separete_by_comma (temp05, temp12, temp11); separete_by_comma (temp06, temp11, temp12); separete_by_comma (temp07, temp12, temp11); separete_by_comma (temp08, temp11, temp12); // printf("result [%s],[%s],[%s],[%s],[%s]\n",temp04,temp05,temp06,temp07,temp08); disk_io_num = (int) atoi (temp05) + (int) atoi (temp07); printf ("disk io %d[times]\n", disk_io_num); } if (!strcmp (temp1, "ctxt")) { itemp2 = (int) (atoi (temp2)); printf ("Context switch %d[times]\n", itemp2); } if (!strcmp (temp1, "btime")) { long timesec; timesec = (long) (atol (temp2)); struct tm *tmp; char *asctm; tmp = localtime (×ec); asctm = asctime (tmp); printf ("Boot at : %s", asctm); } if (!strcmp (temp1, "processes")) { itemp2 = (int) (atoi (temp2)); printf ("forked processes %d.\n", itemp2); } } } //-------------------------------------- //指定時間待つ // interval 秒 void sleep (int interval) { //現在時刻の取得 time_t start_time; start_time = time ((time_t *) 0); //****************************** //疑問 // time_t *start_time; // *start_time = time( (time_t *)0 ); //だとセグメンテーションフォルトなのはなぜ? // //あるいは // time_t *start_time; // *start_time = time(); //でもセグメンテーションフォルトなのは、なぜ? //****************************** time_t current_time; current_time = time ((time_t *) 0); double past_time; do { current_time = time ((time_t *) 0); past_time = (double) (current_time - start_time); } while (((double) interval) > past_time); } //-------------------------------------- //呼出し時のメモリ負荷を返す double sampleLoadAvg () { // printf ("sampleLoadAvg()\n"); FILE *thisProcFile; char lineBuf[LB_SIZE]; char memInfo[LB_SIZE]; char strTemp[LB_SIZE]; char strUsedMem[LB_SIZE]; char strFreeMem[LB_SIZE]; char strTotalMem[LB_SIZE]; double UsedMem; double FreeMem; double TotalMem; int num; double Load; thisProcFile = fopen ("/proc/meminfo", "r"); while (fgets (lineBuf, LB_SIZE, thisProcFile)) { num = sscanf (lineBuf, "%s %s %s %s", strTemp, strTotalMem, strUsedMem, strFreeMem); if (!strcmp (strTemp, "Mem:")) { // printf ("%s %s %s %s\n", strTemp, strTotalMem, strUsedMem, // strFreeMem); TotalMem = atof (strTotalMem); UsedMem = atof (strUsedMem); FreeMem = atof (strFreeMem); Load = (UsedMem / TotalMem * 100); // printf("Load = Used[%f]/Total[%f] = %3.2f[%]\n",UsedMem,TotalMem,Load); printf("Load = %3.2f[%]\n",Load); break; } } close (thisProcFile); return( Load ); } //-------------------------------------- // 以下の情報を出力する。 // このコンピュータに設定されているメモリサイズ // 現在利用可能なメモリサイズ // 負荷平均のリスト(それぞれ最後の一分間に平均されたもの) void doLong (int interval, int duration) { double Load = 0; int count = 0; // printf ("doLong( %d 秒毎に %d 秒間 )\n", interval, duration); int iteration = 0; while (iteration < duration) { sleep (interval); // printf ("[iteration:%3d] ", iteration); Load += sampleLoadAvg (); count++; iteration += interval; } printf("Load Average = %3.2f[%]\n",(Load / count)); // printf ("doLong() end.\n"); } //------------------------------------- // Main Routine //------------------------------------- int main (int argc, char *argv[]) { char repTypeName[16]; int reportType; FILE *thisProcFile; char lineBuf[LB_SIZE]; char c1, c2; int interval; int duration; struct timeval now; char cpuType[LB_SIZE]; char cpuModel[LB_SIZE]; char kernelVersion[LB_SIZE]; char upTime[LB_SIZE]; char value_name[LB_SIZE]; char value_string[LB_SIZE]; char *temp; //レポートの種類を決定する reportType = STANDARD; strcpy (repTypeName, "Standard"); if (argc > 1) { sscanf (argv[1], "%c%c", &c1, &c2); if (c1 != '-') { fprintf (stderr, "usage: ksamp [-s][-l interval duration]\n"); exit (1); } if (c2 == 's') { reportType = SHORT; strcpy (repTypeName, "Short"); } if (c2 == 'l') { if (argc == 4) { reportType = LONG; strcpy (repTypeName, "Long"); interval = atoi (argv[2]); duration = atoi (argv[3]); } else { reportType = SHORT; } } } // doHeader (repTypeName); if (reportType == STANDARD) { doStandard (); } if (reportType == SHORT) { doStandard (); doShort (); } if (reportType == LONG) { doStandard (); doShort (); doLong (interval, duration); } exit (0); }