|
@ -0,0 +1,924 @@ |
|
|
|
|
|
#include <stdio.h> //标准I/O库 |
|
|
|
|
|
#include <stdlib.h> //实用程序库函数 |
|
|
|
|
|
#include <string.h> //字符串操作 |
|
|
|
|
|
#include <signal.h> // 信号 |
|
|
|
|
|
#include <curses.h> |
|
|
|
|
|
#include <limits.h> //实现常量 |
|
|
|
|
|
#include <termcap.h> |
|
|
|
|
|
#include <termios.h> |
|
|
|
|
|
#include <time.h> //时间和日期 |
|
|
|
|
|
#include <errno.h> //出错码 |
|
|
|
|
|
#include <assert.h> //验证程序断言 |
|
|
|
|
|
|
|
|
|
|
|
#include <dirent.h> //目录项 |
|
|
|
|
|
#include <fcntl.h> //文件控制 |
|
|
|
|
|
#include <pwd.h> //口令文件 |
|
|
|
|
|
#include <unistd.h> //符号常量 |
|
|
|
|
|
|
|
|
|
|
|
#include <minix/com.h> |
|
|
|
|
|
#include <minix/config.h> |
|
|
|
|
|
#include <minix/type.h> |
|
|
|
|
|
#include <minix/endpoint.h> |
|
|
|
|
|
#include <minix/const.h> |
|
|
|
|
|
#include <minix/u64.h> |
|
|
|
|
|
#include <paths.h> |
|
|
|
|
|
#include <minix/procfs.h> |
|
|
|
|
|
|
|
|
|
|
|
#include <sys/stat.h> //文件状态 |
|
|
|
|
|
#include <sys/types.h> //基本系统数据类型 |
|
|
|
|
|
#include <sys/wait.h> //进程控制 |
|
|
|
|
|
#include <sys/times.h> //进程时间 |
|
|
|
|
|
#include <sys/time.h> |
|
|
|
|
|
#include <sys/select.h> //select函数 |
|
|
|
|
|
|
|
|
|
|
|
//一般的命令0 |
|
|
|
|
|
//输出重定向1 |
|
|
|
|
|
//输入重定向2 |
|
|
|
|
|
//命令中有管道3 |
|
|
|
|
|
//#define SELF ((endpoint_t) 0x8ace) /* used to indicate 'own process' */ |
|
|
|
|
|
//#define _MAX_MAGIC_PROC (SELF) /* used by <minix/endpoint.h> */ |
|
|
|
|
|
//#define MAX_NR_TASKS 1023 |
|
|
|
|
|
//#define _ENDPOINT_GENERATION_SIZE (MAX_NR_TASKS+_MAX_MAGIC_PROC+1) |
|
|
|
|
|
//#define _ENDPOINT_P(e) |
|
|
|
|
|
//((((e)+1023) % (1023+((endpoint_t) 0x8ace)+1)) - 1023) |
|
|
|
|
|
//#define SLOT_NR(e) (_ENDPOINT_P(e) + nr_tasks) |
|
|
|
|
|
|
|
|
|
|
|
#define _PATH_PROC "/proc/" |
|
|
|
|
|
#define PSINFO_VERSION 0 |
|
|
|
|
|
#define TYPE_TASK 'T' |
|
|
|
|
|
#define TYPE_SYSTEM 'S' |
|
|
|
|
|
#define TYPE_USER 'U' |
|
|
|
|
|
#define STATE_RUN 'R' |
|
|
|
|
|
#define TIMECYCLEKEY 't' |
|
|
|
|
|
#define ORDERKEY 'o' |
|
|
|
|
|
|
|
|
|
|
|
#define USED 0x1 |
|
|
|
|
|
#define IS_TASK 0x2 |
|
|
|
|
|
#define IS_SYSTEM 0x4 |
|
|
|
|
|
#define BLOCKED 0x8 |
|
|
|
|
|
|
|
|
|
|
|
#define ORDER_CPU 0 |
|
|
|
|
|
#define ORDER_MEMORY 1 |
|
|
|
|
|
#define ORDER_HIGHEST ORDER_MEMORY |
|
|
|
|
|
|
|
|
|
|
|
#define TC_BUFFER 1024 /* Size of termcap(3) buffer */ |
|
|
|
|
|
#define TC_STRINGS 200 /* Enough room for cm,cl,so,se */ |
|
|
|
|
|
|
|
|
|
|
|
/* name of cpu cycle types, in the order they appear in /psinfo. */ |
|
|
|
|
|
const char *cputimenames[] = {"user", "ipc", "kernelcall"}; |
|
|
|
|
|
#define CPUTIMENAMES (sizeof(cputimenames) / sizeof(cputimenames[0])) |
|
|
|
|
|
|
|
|
|
|
|
#define CPUTIME(m, i) (m & (1L << (i))) |
|
|
|
|
|
|
|
|
|
|
|
struct proc |
|
|
|
|
|
{ |
|
|
|
|
|
int p_flags; // |
|
|
|
|
|
endpoint_t p_endpoint; //端点 |
|
|
|
|
|
pid_t p_pid; //进程号 |
|
|
|
|
|
u64_t p_cpucycles[CPUTIMENAMES]; //cpu周期 |
|
|
|
|
|
int p_priority; //动态优先级 |
|
|
|
|
|
endpoint_t p_blocked; //阻塞状态 |
|
|
|
|
|
time_t p_user_time; //用户时间 |
|
|
|
|
|
vir_bytes p_memory; //内存 |
|
|
|
|
|
uid_t p_effuid; //有效用户ID |
|
|
|
|
|
int p_nice; //静态优先级 |
|
|
|
|
|
char p_name[PROC_NAME_LEN + 1]; //名字 |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
struct proc *proc = NULL, *prev_proc = NULL; |
|
|
|
|
|
|
|
|
|
|
|
struct tp |
|
|
|
|
|
{ |
|
|
|
|
|
struct proc *p; |
|
|
|
|
|
u64_t ticks; |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
void getOrder(char *); //得到输入的命令 |
|
|
|
|
|
void anaOrder(char *, int *, char (*)[256]); //对输入的命令进行解析 |
|
|
|
|
|
void exeCommand(int, char (*)[256]); //执行命令 |
|
|
|
|
|
int checkCommand(char *command); //查找命令中的可执行程序 |
|
|
|
|
|
void getkinfo(); //读取/proc/kinfo得到总的进程和任务数nr_total |
|
|
|
|
|
int print_memory(); //输出内存信息 |
|
|
|
|
|
void get_procs(); //记录当前进程,赋值给prev_proc |
|
|
|
|
|
void parse_dir(); //获取到/proc/下的所有进程pid |
|
|
|
|
|
void parse_file(pid_t pid); //获取每一个进程信息 |
|
|
|
|
|
u64_t cputicks(struct proc *p1, struct proc *p2, int timemode); //计算每个进程的滴答 |
|
|
|
|
|
void print_procs(struct proc *proc1, struct proc *proc2, int cputimemode); //输出CPU使用时间 |
|
|
|
|
|
|
|
|
|
|
|
char *message; //用于myshell提示信息的输出 |
|
|
|
|
|
int whilecnt = 0; |
|
|
|
|
|
char msg[40][256]; |
|
|
|
|
|
unsigned int nr_procs, nr_tasks; //进程数和任务数 |
|
|
|
|
|
int nr_total; //进程和任务总数 |
|
|
|
|
|
int order = ORDER_CPU; |
|
|
|
|
|
int blockedverbose = 0; |
|
|
|
|
|
char *Tclr_all; |
|
|
|
|
|
int slot = 1; |
|
|
|
|
|
|
|
|
|
|
|
/*static inline u64_t make64(unsigned long lo, unsigned long hi) |
|
|
|
|
|
{ |
|
|
|
|
|
return ((u64_t)hi << 32) | (u64_t)lo; |
|
|
|
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
/* |
|
|
|
|
|
函数名: memset |
|
|
|
|
|
功 能: 设置s中的所有字节为ch, s数组的大小由n给定 |
|
|
|
|
|
用 法: void *memset(void *s, char ch, unsigned n); |
|
|
|
|
|
程序例: |
|
|
|
|
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
#include <mem.h> |
|
|
|
|
|
|
|
|
|
|
|
int main(void) |
|
|
|
|
|
{ |
|
|
|
|
|
char buffer[] = "Hello world\n"; |
|
|
|
|
|
|
|
|
|
|
|
printf("Buffer before memset: %s\n", buffer); |
|
|
|
|
|
memset(buffer, '*', strlen(buffer) - 1); |
|
|
|
|
|
printf("Buffer after memset: %s\n", buffer); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
/* |
|
|
|
|
|
函数名: getcwd |
|
|
|
|
|
功 能: 取当前工作目录 |
|
|
|
|
|
用 法: char *getcwd(char *buf, int n); |
|
|
|
|
|
程序例: |
|
|
|
|
|
#include <stdio.h> |
|
|
|
|
|
#include <dir.h> |
|
|
|
|
|
int main(void) |
|
|
|
|
|
{ |
|
|
|
|
|
char buffer[MAXPATH]; |
|
|
|
|
|
|
|
|
|
|
|
getcwd(buffer, MAXPATH); |
|
|
|
|
|
printf("The current directory is: %s\n", buffer); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv) |
|
|
|
|
|
{ |
|
|
|
|
|
int i; |
|
|
|
|
|
int wordcount = 0; |
|
|
|
|
|
char wordmatrix[100][256]; |
|
|
|
|
|
char **arg = NULL; |
|
|
|
|
|
char *buf = NULL; //用户输入 |
|
|
|
|
|
|
|
|
|
|
|
if ((buf = (char *)malloc(256)) == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
perror("malloc failed"); |
|
|
|
|
|
exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
while (1) |
|
|
|
|
|
{ |
|
|
|
|
|
memset(buf, 0, 256); //将buf所指的空间清零 |
|
|
|
|
|
message = (char *)malloc(100); |
|
|
|
|
|
getcwd(message, 100); |
|
|
|
|
|
printf("myshell:%s# ", message); |
|
|
|
|
|
free(message); |
|
|
|
|
|
getOrder(buf); |
|
|
|
|
|
strcpy(msg[whilecnt], buf); |
|
|
|
|
|
whilecnt++; |
|
|
|
|
|
if (strcmp(buf, "exit\n") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
for (i = 0; i < 100; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
wordmatrix[i][0] = '\0'; |
|
|
|
|
|
} |
|
|
|
|
|
wordcount = 0; |
|
|
|
|
|
anaOrder(buf, &wordcount, wordmatrix); |
|
|
|
|
|
exeCommand(wordcount, wordmatrix); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (buf != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
free(buf); |
|
|
|
|
|
buf = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//获取用户输入 |
|
|
|
|
|
void getOrder(char *buf) |
|
|
|
|
|
{ |
|
|
|
|
|
int cnt = 0; |
|
|
|
|
|
|
|
|
|
|
|
int c = getchar(); |
|
|
|
|
|
while (cnt < 256 && c != '\n') |
|
|
|
|
|
{ |
|
|
|
|
|
buf[cnt++] = c; |
|
|
|
|
|
c = getchar(); |
|
|
|
|
|
} |
|
|
|
|
|
buf[cnt++] = '\n'; |
|
|
|
|
|
buf[cnt] = '\0'; |
|
|
|
|
|
if (cnt == 256) |
|
|
|
|
|
{ |
|
|
|
|
|
exit(-1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//解析buf中的命令,将结果存入wordmatrix中,命令以回车符号\n结束 |
|
|
|
|
|
void anaOrder(char *buf, int *wordcount, char (*wordmatrix)[256]) |
|
|
|
|
|
{ |
|
|
|
|
|
char *p = buf; |
|
|
|
|
|
char *q = buf; |
|
|
|
|
|
int number = 0; |
|
|
|
|
|
int i; |
|
|
|
|
|
while (1) |
|
|
|
|
|
{ |
|
|
|
|
|
if (p[0] == '\n') |
|
|
|
|
|
{ |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
if (p[0] == ' ') |
|
|
|
|
|
{ |
|
|
|
|
|
p++; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
q = p; |
|
|
|
|
|
number = 0; |
|
|
|
|
|
while ((q[0] != ' ') && (q[0] != '\n')) |
|
|
|
|
|
{ |
|
|
|
|
|
if (q[0] == 92) |
|
|
|
|
|
{ |
|
|
|
|
|
q[0] = ' '; |
|
|
|
|
|
q[1] = q[2]; |
|
|
|
|
|
for (i = 2;; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
q[i] = q[i + 1]; |
|
|
|
|
|
if ((q[i] == ' ') || (q[i] == '\n')) |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
number++; |
|
|
|
|
|
q++; |
|
|
|
|
|
} |
|
|
|
|
|
strncpy(wordmatrix[*wordcount], p, number + 1); |
|
|
|
|
|
wordmatrix[*wordcount][number] = '\0'; |
|
|
|
|
|
*wordcount = *wordcount + 1; |
|
|
|
|
|
p = q; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
/* |
|
|
|
|
|
函数名: dup2 |
|
|
|
|
|
功 能: 复制文件句柄 |
|
|
|
|
|
用 法: int dup2(int oldhandle, int newhandle); |
|
|
|
|
|
程序例: |
|
|
|
|
|
|
|
|
|
|
|
#include <sys\stat.h> |
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
#include <fcntl.h> |
|
|
|
|
|
#include <io.h> |
|
|
|
|
|
|
|
|
|
|
|
int main(void) |
|
|
|
|
|
{ |
|
|
|
|
|
#define STDOUT 1 |
|
|
|
|
|
|
|
|
|
|
|
int nul, oldstdout; |
|
|
|
|
|
char msg[] = "This is a test"; |
|
|
|
|
|
|
|
|
|
|
|
//create a file |
|
|
|
|
|
nul = open("DUMMY.FIL", O_CREAT | O_RDWR, |
|
|
|
|
|
S_IREAD | S_IWRITE); |
|
|
|
|
|
|
|
|
|
|
|
//create a duplicate handle for standard output |
|
|
|
|
|
oldstdout = dup(STDOUT); |
|
|
|
|
|
redirect standard output to DUMMY.FIL |
|
|
|
|
|
by duplicating the file handle onto the |
|
|
|
|
|
file handle for standard output. |
|
|
|
|
|
dup2(nul, STDOUT); |
|
|
|
|
|
|
|
|
|
|
|
close the handle for DUMMY.FIL |
|
|
|
|
|
close(nul); |
|
|
|
|
|
|
|
|
|
|
|
will be redirected into DUMMY.FIL |
|
|
|
|
|
write(STDOUT, msg, strlen(msg)); |
|
|
|
|
|
|
|
|
|
|
|
restore original standard output handle |
|
|
|
|
|
dup2(oldstdout, STDOUT); |
|
|
|
|
|
|
|
|
|
|
|
//close duplicate handle for STDOUT |
|
|
|
|
|
close(oldstdout); |
|
|
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
void exeCommand(int wordcount, char (*wordmatrix)[256]) |
|
|
|
|
|
{ |
|
|
|
|
|
pid_t pid; |
|
|
|
|
|
char *file; |
|
|
|
|
|
int correct = 1; |
|
|
|
|
|
int way = 0; |
|
|
|
|
|
int status; |
|
|
|
|
|
int i; |
|
|
|
|
|
int fd; |
|
|
|
|
|
char *word[wordcount + 1]; |
|
|
|
|
|
char *wordnext[wordcount + 1]; |
|
|
|
|
|
|
|
|
|
|
|
//将命令取出 |
|
|
|
|
|
for (i = 0; i < wordcount; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
word[i] = (char *)wordmatrix[i]; |
|
|
|
|
|
} |
|
|
|
|
|
word[wordcount] = NULL; |
|
|
|
|
|
|
|
|
|
|
|
//查看命令行是否有后台运行符 |
|
|
|
|
|
for (i = 0; i < wordcount; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
if (strncmp(word[i], "&", 1) == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
way = 4; |
|
|
|
|
|
word[wordcount - 1] = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; word[i] != NULL; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
if (strcmp(word[i], ">") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
way = 1; |
|
|
|
|
|
if (word[i + 1] == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
correct = 0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (strcmp(word[i], "<") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
way = 2; |
|
|
|
|
|
if (i == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
correct = 0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (strcmp(word[i], "|") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
way = 3; |
|
|
|
|
|
if (word[i + 1] == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
correct = 0; |
|
|
|
|
|
} |
|
|
|
|
|
if (i == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
correct = 0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
//correct=0,说明命令格式不对 |
|
|
|
|
|
if (correct == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("wrong format\n"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (way == 1) |
|
|
|
|
|
{ |
|
|
|
|
|
//输出重定向 |
|
|
|
|
|
for (i = 0; word[i] != NULL; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
if (strcmp(word[i], ">") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
file = word[i + 1]; |
|
|
|
|
|
word[i] = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (way == 2) |
|
|
|
|
|
{ |
|
|
|
|
|
//输入重定向 |
|
|
|
|
|
for (i = 0; word[i] != NULL; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
if (strcmp(word[i], "<") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
file = word[i + 1]; |
|
|
|
|
|
word[i] = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (way == 3) |
|
|
|
|
|
{ |
|
|
|
|
|
//把管道符后面的部分存入wordnext中,管道后面的部分是一个可执行的shell命令 |
|
|
|
|
|
for (i = 0; word[i] != NULL; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
if (strcmp(word[i], "|") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
word[i] = NULL; |
|
|
|
|
|
int j; |
|
|
|
|
|
for (j = i + 1; word[j] != NULL; j++) |
|
|
|
|
|
{ |
|
|
|
|
|
wordnext[j - i - 1] = word[j]; |
|
|
|
|
|
} |
|
|
|
|
|
wordnext[j - i - 1] = NULL; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (strcmp(word[0], "cd") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if (word[1] == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (chdir(word[1]) == -1) |
|
|
|
|
|
{ |
|
|
|
|
|
perror("cd"); |
|
|
|
|
|
} |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((pid = fork()) < 0) |
|
|
|
|
|
{ //创建子进程 |
|
|
|
|
|
printf("fork error\n"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (strcmp(word[0], "history") == 0) |
|
|
|
|
|
{ //实现history n |
|
|
|
|
|
if (pid == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
char cnum = word[1][0]; |
|
|
|
|
|
int num = cnum - 48; |
|
|
|
|
|
for (int i = whilecnt - 1; i > whilecnt - num - 1; i--) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("command %d:", i); |
|
|
|
|
|
printf("%s", msg[i]); |
|
|
|
|
|
} |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (strcmp(word[0], "mytop") == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if (pid == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
int cputimemode = 1; |
|
|
|
|
|
getkinfo(); |
|
|
|
|
|
print_memory(); |
|
|
|
|
|
get_procs(); |
|
|
|
|
|
if (prev_proc == NULL) |
|
|
|
|
|
get_procs(); |
|
|
|
|
|
print_procs(prev_proc, proc, cputimemode); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch (way) |
|
|
|
|
|
{ |
|
|
|
|
|
case 0: |
|
|
|
|
|
//pid为0说明是子进程,在子进程中执行输入的命令 |
|
|
|
|
|
//输入的命令中不含> < | & |
|
|
|
|
|
if (pid == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!(checkCommand(word[0]))) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s : command not found\n", word[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
execvp(word[0], word); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 1: |
|
|
|
|
|
//输入的命令中含有输出重定向符 |
|
|
|
|
|
if (pid == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!(checkCommand(word[0]))) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s : command not found\n", word[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0644); |
|
|
|
|
|
dup2(fd, 1); |
|
|
|
|
|
execvp(word[0], word); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 2: |
|
|
|
|
|
//输入的命令中含有输入重定向< |
|
|
|
|
|
if (pid == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!(checkCommand(word[0]))) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s : command not found\n", word[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
fd = open(file, O_RDONLY); |
|
|
|
|
|
dup2(fd, 0); |
|
|
|
|
|
execvp(word[0], word); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 3: |
|
|
|
|
|
//输入的命令中含有管道符| |
|
|
|
|
|
if (pid == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
int pid2; |
|
|
|
|
|
int status2; |
|
|
|
|
|
int fd[2]; |
|
|
|
|
|
|
|
|
|
|
|
if (pipe(fd) < 0) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("pipe error\n"); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((pid2 = fork()) < 0) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("fork2 error\n"); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
else if (pid2 == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!(checkCommand(word[0]))) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s : command not found\n", word[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
dup2(fd[1], 1); |
|
|
|
|
|
execvp(word[0], word); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
if (waitpid(pid2, &status2, 0) == -1) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("wait for child process error\n"); |
|
|
|
|
|
} |
|
|
|
|
|
if (!(checkCommand(wordnext[0]))) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s : command not found\n", wordnext[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
dup2(fd[0], 0); |
|
|
|
|
|
execvp(wordnext[0], wordnext); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
case 4: //若命令中有&,表示后台执行,父进程直接返回,不等待子进程结束 |
|
|
|
|
|
signal(SIGCHLD, SIG_IGN); |
|
|
|
|
|
if (pid == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
//int pidbg; |
|
|
|
|
|
//pidbg=fork(); |
|
|
|
|
|
//if(pidbg==0){ |
|
|
|
|
|
printf("[process id: %d]\n", pid); |
|
|
|
|
|
int a = open("/dev/null", O_RDONLY); |
|
|
|
|
|
dup2(a, 0); |
|
|
|
|
|
dup2(a, 1); |
|
|
|
|
|
if (!(checkCommand(word[0]))) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("%s : command not found\n", word[0]); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
} |
|
|
|
|
|
execvp(word[0], word); |
|
|
|
|
|
exit(0); |
|
|
|
|
|
//} |
|
|
|
|
|
} |
|
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//父进程等待子进程结束 |
|
|
|
|
|
if (waitpid(pid, &status, 0) == -1) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("wait for child process error\n"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//查找命令中的可执行程序 |
|
|
|
|
|
int checkCommand(char *command) |
|
|
|
|
|
{ |
|
|
|
|
|
DIR *dp; |
|
|
|
|
|
struct dirent *dirp; |
|
|
|
|
|
char *path[] = {"./", "/bin", "/usr/bin", NULL}; |
|
|
|
|
|
|
|
|
|
|
|
if (strncmp(command, "./", 2) == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
command = command + 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//分别在当前目录,/bin和/usr/bin目录查找要执行的程序 |
|
|
|
|
|
int i = 0; |
|
|
|
|
|
while (path[i] != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
if ((dp = opendir(path[i])) == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
printf("can not open /bin \n"); |
|
|
|
|
|
} |
|
|
|
|
|
while ((dirp = readdir(dp)) != NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
if (strcmp(dirp->d_name, command) == 0) |
|
|
|
|
|
{ |
|
|
|
|
|
closedir(dp); |
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
closedir(dp); |
|
|
|
|
|
i++; |
|
|
|
|
|
} |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void getkinfo() |
|
|
|
|
|
{ |
|
|
|
|
|
FILE *fp; |
|
|
|
|
|
|
|
|
|
|
|
if ((fp = fopen("/proc/kinfo", "r")) == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
fprintf(stderr, "opening " _PATH_PROC "kinfo failed\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fscanf(fp, "%u %u", &nr_procs, &nr_tasks) != 2) |
|
|
|
|
|
{ |
|
|
|
|
|
fprintf(stderr, "reading from " _PATH_PROC "kinfo failed\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
|
|
|
|
|
|
nr_total = (int)(nr_procs + nr_tasks); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int print_memory() |
|
|
|
|
|
{ |
|
|
|
|
|
FILE *fp; |
|
|
|
|
|
unsigned int pagesize; |
|
|
|
|
|
unsigned long total, free, largest, cached; |
|
|
|
|
|
|
|
|
|
|
|
if ((fp = fopen("/proc/meminfo", "r")) == NULL) |
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
|
|
if (fscanf(fp, "%u %lu %lu %lu %lu", &pagesize, &total, &free, |
|
|
|
|
|
&largest, &cached) != 5) |
|
|
|
|
|
{ |
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
return 0; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
|
|
|
|
|
|
printf("main memory: %ldK total, %ldK free, %ldK contig free, " |
|
|
|
|
|
"%ldK cached\n", |
|
|
|
|
|
(pagesize * total) / 1024, (pagesize * free) / 1024, |
|
|
|
|
|
(pagesize * largest) / 1024, (pagesize * cached) / 1024); |
|
|
|
|
|
|
|
|
|
|
|
return 1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void get_procs() |
|
|
|
|
|
{ |
|
|
|
|
|
struct proc *p; |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
p = prev_proc; |
|
|
|
|
|
prev_proc = proc; |
|
|
|
|
|
proc = p; |
|
|
|
|
|
|
|
|
|
|
|
if (proc == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
proc = malloc(nr_total * sizeof(proc[0])); |
|
|
|
|
|
|
|
|
|
|
|
if (proc == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
fprintf(stderr, "Out of memory!\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < nr_total; i++) |
|
|
|
|
|
proc[i].p_flags = 0; |
|
|
|
|
|
|
|
|
|
|
|
parse_dir(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void parse_dir() |
|
|
|
|
|
{ |
|
|
|
|
|
DIR *p_dir; |
|
|
|
|
|
struct dirent *p_ent; |
|
|
|
|
|
pid_t pid; |
|
|
|
|
|
char *end; //end是指向第一个不可转换的字符位置的指针 |
|
|
|
|
|
|
|
|
|
|
|
if ((p_dir = opendir("/proc")) == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
perror("opendir on " _PATH_PROC); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (p_ent = readdir(p_dir); p_ent != NULL; p_ent = readdir(p_dir)) |
|
|
|
|
|
{ |
|
|
|
|
|
pid = strtol(p_ent->d_name, &end, 10); //long strtol(char *str, char **endptr, int base)将串转换为长整数,base是基数,表示要转换的是几进制的数 |
|
|
|
|
|
|
|
|
|
|
|
if (!end[0] && pid != 0) |
|
|
|
|
|
parse_file(pid); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
closedir(p_dir); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void parse_file(pid_t pid) |
|
|
|
|
|
{ |
|
|
|
|
|
char path[PATH_MAX], name[256], type, state; |
|
|
|
|
|
int version, endpt, effuid; //版本,端点,有效用户ID |
|
|
|
|
|
unsigned long cycles_hi, cycles_lo; //高周期,低周期 |
|
|
|
|
|
FILE *fp; |
|
|
|
|
|
struct proc *p; |
|
|
|
|
|
//int slot; //插槽? |
|
|
|
|
|
int i; |
|
|
|
|
|
//printf("parse_file\n"); |
|
|
|
|
|
|
|
|
|
|
|
sprintf(path, "/proc/%d/psinfo", pid); |
|
|
|
|
|
|
|
|
|
|
|
if ((fp = fopen(path, "r")) == NULL) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
if (fscanf(fp, "%d", &version) != 1) |
|
|
|
|
|
{ |
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (version != PSINFO_VERSION) |
|
|
|
|
|
{ //0 |
|
|
|
|
|
fputs("procfs version mismatch!\n", stderr); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (fscanf(fp, " %c %d", &type, &endpt) != 2) |
|
|
|
|
|
{ |
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
slot++; |
|
|
|
|
|
//slot = SLOT_NR(endpt); |
|
|
|
|
|
|
|
|
|
|
|
if (slot < 0 || slot >= nr_total) |
|
|
|
|
|
{ |
|
|
|
|
|
fprintf(stderr, "top: unreasonable endpoint number %d\n", endpt); |
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
p = &proc[slot]; |
|
|
|
|
|
|
|
|
|
|
|
if (type == TYPE_TASK) |
|
|
|
|
|
p->p_flags |= IS_TASK; |
|
|
|
|
|
else if (type == TYPE_SYSTEM) |
|
|
|
|
|
p->p_flags |= IS_SYSTEM; |
|
|
|
|
|
|
|
|
|
|
|
p->p_endpoint = endpt; |
|
|
|
|
|
p->p_pid = pid; |
|
|
|
|
|
|
|
|
|
|
|
if (fscanf(fp, " %255s %c %d %d %lu %*u %lu %lu", |
|
|
|
|
|
name, &state, &p->p_blocked, &p->p_priority, |
|
|
|
|
|
&p->p_user_time, &cycles_hi, &cycles_lo) != 7) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
strncpy(p->p_name, name, sizeof(p->p_name) - 1); |
|
|
|
|
|
p->p_name[sizeof(p->p_name) - 1] = 0; |
|
|
|
|
|
|
|
|
|
|
|
if (state != STATE_RUN) |
|
|
|
|
|
p->p_flags |= BLOCKED; |
|
|
|
|
|
p->p_cpucycles[0] = make64(cycles_lo, cycles_hi); |
|
|
|
|
|
p->p_memory = 0L; |
|
|
|
|
|
|
|
|
|
|
|
if (!(p->p_flags & IS_TASK)) |
|
|
|
|
|
{ |
|
|
|
|
|
int j; |
|
|
|
|
|
if ((j = fscanf(fp, " %lu %*u %*u %*c %*d %*u %u %*u %d %*c %*d %*u", |
|
|
|
|
|
&p->p_memory, &effuid, &p->p_nice)) != 3) |
|
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
p->p_effuid = effuid; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
p->p_effuid = 0; |
|
|
|
|
|
|
|
|
|
|
|
for (i = 1; i < CPUTIMENAMES; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
if (fscanf(fp, " %lu %lu", |
|
|
|
|
|
&cycles_hi, &cycles_lo) == 2) |
|
|
|
|
|
{ |
|
|
|
|
|
p->p_cpucycles[i] = make64(cycles_lo, cycles_hi); |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
p->p_cpucycles[i] = 0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if ((p->p_flags & IS_TASK)) |
|
|
|
|
|
{ |
|
|
|
|
|
if (fscanf(fp, " %lu", &p->p_memory) != 1) |
|
|
|
|
|
{ |
|
|
|
|
|
p->p_memory = 0; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
p->p_flags |= USED; |
|
|
|
|
|
|
|
|
|
|
|
fclose(fp); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
u64_t cputicks(struct proc *p1, struct proc *p2, int timemode) |
|
|
|
|
|
{ |
|
|
|
|
|
int i; |
|
|
|
|
|
u64_t t = 0; |
|
|
|
|
|
for (i = 0; i < CPUTIMENAMES; i++) |
|
|
|
|
|
{ |
|
|
|
|
|
if (!CPUTIME(timemode, i)) |
|
|
|
|
|
continue; |
|
|
|
|
|
if (p1->p_endpoint == p2->p_endpoint) |
|
|
|
|
|
{ |
|
|
|
|
|
t = t + p2->p_cpucycles[i] - p1->p_cpucycles[i]; |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
t = t + p2->p_cpucycles[i]; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return t; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void print_procs(struct proc *proc1, struct proc *proc2, int cputimemode) |
|
|
|
|
|
{ |
|
|
|
|
|
int p, nprocs; |
|
|
|
|
|
//u64_t idleticks = 0; |
|
|
|
|
|
//u64_t kernelticks = 0; |
|
|
|
|
|
u64_t systemticks = 0; |
|
|
|
|
|
u64_t userticks = 0; |
|
|
|
|
|
u64_t total_ticks = 0; |
|
|
|
|
|
int blockedseen = 0; |
|
|
|
|
|
static struct tp *tick_procs = NULL; //tp结构体的数组tick_procs,对所有的进程和任务(即上面读出来的nr_total)计算ticks |
|
|
|
|
|
|
|
|
|
|
|
if (tick_procs == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
tick_procs = malloc(nr_total * sizeof(tick_procs[0])); |
|
|
|
|
|
|
|
|
|
|
|
if (tick_procs == NULL) |
|
|
|
|
|
{ |
|
|
|
|
|
fprintf(stderr, "Out of memory!\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (p = nprocs = 0; p < nr_total; p++) |
|
|
|
|
|
{ |
|
|
|
|
|
u64_t uticks; |
|
|
|
|
|
if (!(proc2[p].p_flags & USED)) |
|
|
|
|
|
continue; |
|
|
|
|
|
tick_procs[nprocs].p = proc2 + p; |
|
|
|
|
|
tick_procs[nprocs].ticks = cputicks(&proc1[p], &proc2[p], cputimemode); |
|
|
|
|
|
uticks = cputicks(&proc1[p], &proc2[p], 1); |
|
|
|
|
|
total_ticks = total_ticks + uticks; |
|
|
|
|
|
//printf("total_ticks:%llu\n",total_ticks); |
|
|
|
|
|
/*if(p-NR_TASKS == IDLE) { |
|
|
|
|
|
idleticks = uticks; |
|
|
|
|
|
continue; |
|
|
|
|
|
} |
|
|
|
|
|
if(p-NR_TASKS == KERNEL) { |
|
|
|
|
|
kernelticks = uticks; |
|
|
|
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
if (!(proc2[p].p_flags & IS_TASK)) |
|
|
|
|
|
{ |
|
|
|
|
|
if (proc2[p].p_flags & IS_SYSTEM) |
|
|
|
|
|
systemticks = systemticks + tick_procs[nprocs].ticks; |
|
|
|
|
|
else |
|
|
|
|
|
userticks = userticks + tick_procs[nprocs].ticks; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
nprocs++; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (total_ticks == 0) |
|
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
printf("CPU states: %6.2f%% user, ", 100.0 * userticks / total_ticks); |
|
|
|
|
|
printf("%6.2f%% system", 100.0 * systemticks / total_ticks); |
|
|
|
|
|
printf("%6.2f%% in total\n", 100.0 * (systemticks + userticks) / total_ticks); |
|
|
|
|
|
//printf("%6.2f%% kernel, ", 100.0 * kernelticks/ total_ticks); |
|
|
|
|
|
//printf("%6.2f%% idle", 100.0 * idleticks / total_ticks); |
|
|
|
|
|
} |