#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);
|
|
}
|