OS2021_Project1.Shell
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

924 lines
22 KiB

преди 3 години
  1. #include <stdio.h> //标准I/O库
  2. #include <stdlib.h> //实用程序库函数
  3. #include <string.h> //字符串操作
  4. #include <signal.h> // 信号
  5. #include <curses.h>
  6. #include <limits.h> //实现常量
  7. #include <termcap.h>
  8. #include <termios.h>
  9. #include <time.h> //时间和日期
  10. #include <errno.h> //出错码
  11. #include <assert.h> //验证程序断言
  12. #include <dirent.h> //目录项
  13. #include <fcntl.h> //文件控制
  14. #include <pwd.h> //口令文件
  15. #include <unistd.h> //符号常量
  16. #include <minix/com.h>
  17. #include <minix/config.h>
  18. #include <minix/type.h>
  19. #include <minix/endpoint.h>
  20. #include <minix/const.h>
  21. #include <minix/u64.h>
  22. #include <paths.h>
  23. #include <minix/procfs.h>
  24. #include <sys/stat.h> //文件状态
  25. #include <sys/types.h> //基本系统数据类型
  26. #include <sys/wait.h> //进程控制
  27. #include <sys/times.h> //进程时间
  28. #include <sys/time.h>
  29. #include <sys/select.h> //select函数
  30. //一般的命令0
  31. //输出重定向1
  32. //输入重定向2
  33. //命令中有管道3
  34. //#define SELF ((endpoint_t) 0x8ace) /* used to indicate 'own process' */
  35. //#define _MAX_MAGIC_PROC (SELF) /* used by <minix/endpoint.h> */
  36. //#define MAX_NR_TASKS 1023
  37. //#define _ENDPOINT_GENERATION_SIZE (MAX_NR_TASKS+_MAX_MAGIC_PROC+1)
  38. //#define _ENDPOINT_P(e)
  39. //((((e)+1023) % (1023+((endpoint_t) 0x8ace)+1)) - 1023)
  40. //#define SLOT_NR(e) (_ENDPOINT_P(e) + nr_tasks)
  41. #define _PATH_PROC "/proc/"
  42. #define PSINFO_VERSION 0
  43. #define TYPE_TASK 'T'
  44. #define TYPE_SYSTEM 'S'
  45. #define TYPE_USER 'U'
  46. #define STATE_RUN 'R'
  47. #define TIMECYCLEKEY 't'
  48. #define ORDERKEY 'o'
  49. #define USED 0x1
  50. #define IS_TASK 0x2
  51. #define IS_SYSTEM 0x4
  52. #define BLOCKED 0x8
  53. #define ORDER_CPU 0
  54. #define ORDER_MEMORY 1
  55. #define ORDER_HIGHEST ORDER_MEMORY
  56. #define TC_BUFFER 1024 /* Size of termcap(3) buffer */
  57. #define TC_STRINGS 200 /* Enough room for cm,cl,so,se */
  58. /* name of cpu cycle types, in the order they appear in /psinfo. */
  59. const char *cputimenames[] = {"user", "ipc", "kernelcall"};
  60. #define CPUTIMENAMES (sizeof(cputimenames) / sizeof(cputimenames[0]))
  61. #define CPUTIME(m, i) (m & (1L << (i)))
  62. struct proc
  63. {
  64. int p_flags; //
  65. endpoint_t p_endpoint; //端点
  66. pid_t p_pid; //进程号
  67. u64_t p_cpucycles[CPUTIMENAMES]; //cpu周期
  68. int p_priority; //动态优先级
  69. endpoint_t p_blocked; //阻塞状态
  70. time_t p_user_time; //用户时间
  71. vir_bytes p_memory; //内存
  72. uid_t p_effuid; //有效用户ID
  73. int p_nice; //静态优先级
  74. char p_name[PROC_NAME_LEN + 1]; //名字
  75. };
  76. struct proc *proc = NULL, *prev_proc = NULL;
  77. struct tp
  78. {
  79. struct proc *p;
  80. u64_t ticks;
  81. };
  82. void getOrder(char *); //得到输入的命令
  83. void anaOrder(char *, int *, char (*)[256]); //对输入的命令进行解析
  84. void exeCommand(int, char (*)[256]); //执行命令
  85. int checkCommand(char *command); //查找命令中的可执行程序
  86. void getkinfo(); //读取/proc/kinfo得到总的进程和任务数nr_total
  87. int print_memory(); //输出内存信息
  88. void get_procs(); //记录当前进程,赋值给prev_proc
  89. void parse_dir(); //获取到/proc/下的所有进程pid
  90. void parse_file(pid_t pid); //获取每一个进程信息
  91. u64_t cputicks(struct proc *p1, struct proc *p2, int timemode); //计算每个进程的滴答
  92. void print_procs(struct proc *proc1, struct proc *proc2, int cputimemode); //输出CPU使用时间
  93. char *message; //用于myshell提示信息的输出
  94. int whilecnt = 0;
  95. char msg[40][256];
  96. unsigned int nr_procs, nr_tasks; //进程数和任务数
  97. int nr_total; //进程和任务总数
  98. int order = ORDER_CPU;
  99. int blockedverbose = 0;
  100. char *Tclr_all;
  101. int slot = 1;
  102. /*static inline u64_t make64(unsigned long lo, unsigned long hi)
  103. {
  104. return ((u64_t)hi << 32) | (u64_t)lo;
  105. }
  106. */
  107. /*
  108. : memset
  109. : s中的所有字节为ch, s数组的大小由n给定
  110. : void *memset(void *s, char ch, unsigned n);
  111. :
  112. #include <string.h>
  113. #include <stdio.h>
  114. #include <mem.h>
  115. int main(void)
  116. {
  117. char buffer[] = "Hello world\n";
  118. printf("Buffer before memset: %s\n", buffer);
  119. memset(buffer, '*', strlen(buffer) - 1);
  120. printf("Buffer after memset: %s\n", buffer);
  121. return 0;
  122. }
  123. */
  124. /*
  125. : getcwd
  126. :
  127. : char *getcwd(char *buf, int n);
  128. :
  129. #include <stdio.h>
  130. #include <dir.h>
  131. int main(void)
  132. {
  133. char buffer[MAXPATH];
  134. getcwd(buffer, MAXPATH);
  135. printf("The current directory is: %s\n", buffer);
  136. return 0;
  137. }
  138. */
  139. int main(int argc, char **argv)
  140. {
  141. int i;
  142. int wordcount = 0;
  143. char wordmatrix[100][256];
  144. char **arg = NULL;
  145. char *buf = NULL; //用户输入
  146. if ((buf = (char *)malloc(256)) == NULL)
  147. {
  148. perror("malloc failed");
  149. exit(-1);
  150. }
  151. while (1)
  152. {
  153. memset(buf, 0, 256); //将buf所指的空间清零
  154. message = (char *)malloc(100);
  155. getcwd(message, 100);
  156. printf("myshell:%s# ", message);
  157. free(message);
  158. getOrder(buf);
  159. strcpy(msg[whilecnt], buf);
  160. whilecnt++;
  161. if (strcmp(buf, "exit\n") == 0)
  162. {
  163. break;
  164. }
  165. for (i = 0; i < 100; i++)
  166. {
  167. wordmatrix[i][0] = '\0';
  168. }
  169. wordcount = 0;
  170. anaOrder(buf, &wordcount, wordmatrix);
  171. exeCommand(wordcount, wordmatrix);
  172. }
  173. if (buf != NULL)
  174. {
  175. free(buf);
  176. buf = NULL;
  177. }
  178. return 0;
  179. }
  180. //获取用户输入
  181. void getOrder(char *buf)
  182. {
  183. int cnt = 0;
  184. int c = getchar();
  185. while (cnt < 256 && c != '\n')
  186. {
  187. buf[cnt++] = c;
  188. c = getchar();
  189. }
  190. buf[cnt++] = '\n';
  191. buf[cnt] = '\0';
  192. if (cnt == 256)
  193. {
  194. exit(-1);
  195. }
  196. }
  197. //解析buf中的命令,将结果存入wordmatrix中,命令以回车符号\n结束
  198. void anaOrder(char *buf, int *wordcount, char (*wordmatrix)[256])
  199. {
  200. char *p = buf;
  201. char *q = buf;
  202. int number = 0;
  203. int i;
  204. while (1)
  205. {
  206. if (p[0] == '\n')
  207. {
  208. break;
  209. }
  210. if (p[0] == ' ')
  211. {
  212. p++;
  213. }
  214. else
  215. {
  216. q = p;
  217. number = 0;
  218. while ((q[0] != ' ') && (q[0] != '\n'))
  219. {
  220. if (q[0] == 92)
  221. {
  222. q[0] = ' ';
  223. q[1] = q[2];
  224. for (i = 2;; i++)
  225. {
  226. q[i] = q[i + 1];
  227. if ((q[i] == ' ') || (q[i] == '\n'))
  228. break;
  229. }
  230. }
  231. number++;
  232. q++;
  233. }
  234. strncpy(wordmatrix[*wordcount], p, number + 1);
  235. wordmatrix[*wordcount][number] = '\0';
  236. *wordcount = *wordcount + 1;
  237. p = q;
  238. }
  239. }
  240. }
  241. /*
  242. : dup2
  243. :
  244. : int dup2(int oldhandle, int newhandle);
  245. :
  246. #include <sys\stat.h>
  247. #include <string.h>
  248. #include <fcntl.h>
  249. #include <io.h>
  250. int main(void)
  251. {
  252. #define STDOUT 1
  253. int nul, oldstdout;
  254. char msg[] = "This is a test";
  255. //create a file
  256. nul = open("DUMMY.FIL", O_CREAT | O_RDWR,
  257. S_IREAD | S_IWRITE);
  258. //create a duplicate handle for standard output
  259. oldstdout = dup(STDOUT);
  260. redirect standard output to DUMMY.FIL
  261. by duplicating the file handle onto the
  262. file handle for standard output.
  263. dup2(nul, STDOUT);
  264. close the handle for DUMMY.FIL
  265. close(nul);
  266. will be redirected into DUMMY.FIL
  267. write(STDOUT, msg, strlen(msg));
  268. restore original standard output handle
  269. dup2(oldstdout, STDOUT);
  270. //close duplicate handle for STDOUT
  271. close(oldstdout);
  272. return 0;
  273. }
  274. */
  275. void exeCommand(int wordcount, char (*wordmatrix)[256])
  276. {
  277. pid_t pid;
  278. char *file;
  279. int correct = 1;
  280. int way = 0;
  281. int status;
  282. int i;
  283. int fd;
  284. char *word[wordcount + 1];
  285. char *wordnext[wordcount + 1];
  286. //将命令取出
  287. for (i = 0; i < wordcount; i++)
  288. {
  289. word[i] = (char *)wordmatrix[i];
  290. }
  291. word[wordcount] = NULL;
  292. //查看命令行是否有后台运行符
  293. for (i = 0; i < wordcount; i++)
  294. {
  295. if (strncmp(word[i], "&", 1) == 0)
  296. {
  297. way = 4;
  298. word[wordcount - 1] = NULL;
  299. }
  300. }
  301. for (i = 0; word[i] != NULL; i++)
  302. {
  303. if (strcmp(word[i], ">") == 0)
  304. {
  305. way = 1;
  306. if (word[i + 1] == NULL)
  307. {
  308. correct = 0;
  309. }
  310. }
  311. if (strcmp(word[i], "<") == 0)
  312. {
  313. way = 2;
  314. if (i == 0)
  315. {
  316. correct = 0;
  317. }
  318. }
  319. if (strcmp(word[i], "|") == 0)
  320. {
  321. way = 3;
  322. if (word[i + 1] == NULL)
  323. {
  324. correct = 0;
  325. }
  326. if (i == 0)
  327. {
  328. correct = 0;
  329. }
  330. }
  331. }
  332. //correct=0,说明命令格式不对
  333. if (correct == 0)
  334. {
  335. printf("wrong format\n");
  336. return;
  337. }
  338. if (way == 1)
  339. {
  340. //输出重定向
  341. for (i = 0; word[i] != NULL; i++)
  342. {
  343. if (strcmp(word[i], ">") == 0)
  344. {
  345. file = word[i + 1];
  346. word[i] = NULL;
  347. }
  348. }
  349. }
  350. if (way == 2)
  351. {
  352. //输入重定向
  353. for (i = 0; word[i] != NULL; i++)
  354. {
  355. if (strcmp(word[i], "<") == 0)
  356. {
  357. file = word[i + 1];
  358. word[i] = NULL;
  359. }
  360. }
  361. }
  362. if (way == 3)
  363. {
  364. //把管道符后面的部分存入wordnext中,管道后面的部分是一个可执行的shell命令
  365. for (i = 0; word[i] != NULL; i++)
  366. {
  367. if (strcmp(word[i], "|") == 0)
  368. {
  369. word[i] = NULL;
  370. int j;
  371. for (j = i + 1; word[j] != NULL; j++)
  372. {
  373. wordnext[j - i - 1] = word[j];
  374. }
  375. wordnext[j - i - 1] = NULL;
  376. }
  377. }
  378. }
  379. if (strcmp(word[0], "cd") == 0)
  380. {
  381. if (word[1] == NULL)
  382. {
  383. return;
  384. }
  385. if (chdir(word[1]) == -1)
  386. {
  387. perror("cd");
  388. }
  389. return;
  390. }
  391. if ((pid = fork()) < 0)
  392. { //创建子进程
  393. printf("fork error\n");
  394. return;
  395. }
  396. if (strcmp(word[0], "history") == 0)
  397. { //实现history n
  398. if (pid == 0)
  399. {
  400. char cnum = word[1][0];
  401. int num = cnum - 48;
  402. for (int i = whilecnt - 1; i > whilecnt - num - 1; i--)
  403. {
  404. printf("command %d:", i);
  405. printf("%s", msg[i]);
  406. }
  407. exit(0);
  408. }
  409. }
  410. if (strcmp(word[0], "mytop") == 0)
  411. {
  412. if (pid == 0)
  413. {
  414. int cputimemode = 1;
  415. getkinfo();
  416. print_memory();
  417. get_procs();
  418. if (prev_proc == NULL)
  419. get_procs();
  420. print_procs(prev_proc, proc, cputimemode);
  421. exit(0);
  422. }
  423. }
  424. switch (way)
  425. {
  426. case 0:
  427. //pid为0说明是子进程,在子进程中执行输入的命令
  428. //输入的命令中不含> < | &
  429. if (pid == 0)
  430. {
  431. if (!(checkCommand(word[0])))
  432. {
  433. printf("%s : command not found\n", word[0]);
  434. exit(0);
  435. }
  436. execvp(word[0], word);
  437. exit(0);
  438. }
  439. break;
  440. case 1:
  441. //输入的命令中含有输出重定向符
  442. if (pid == 0)
  443. {
  444. if (!(checkCommand(word[0])))
  445. {
  446. printf("%s : command not found\n", word[0]);
  447. exit(0);
  448. }
  449. fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0644);
  450. dup2(fd, 1);
  451. execvp(word[0], word);
  452. exit(0);
  453. }
  454. break;
  455. case 2:
  456. //输入的命令中含有输入重定向<
  457. if (pid == 0)
  458. {
  459. if (!(checkCommand(word[0])))
  460. {
  461. printf("%s : command not found\n", word[0]);
  462. exit(0);
  463. }
  464. fd = open(file, O_RDONLY);
  465. dup2(fd, 0);
  466. execvp(word[0], word);
  467. exit(0);
  468. }
  469. break;
  470. case 3:
  471. //输入的命令中含有管道符|
  472. if (pid == 0)
  473. {
  474. int pid2;
  475. int status2;
  476. int fd[2];
  477. if (pipe(fd) < 0)
  478. {
  479. printf("pipe error\n");
  480. exit(0);
  481. }
  482. if ((pid2 = fork()) < 0)
  483. {
  484. printf("fork2 error\n");
  485. return;
  486. }
  487. else if (pid2 == 0)
  488. {
  489. if (!(checkCommand(word[0])))
  490. {
  491. printf("%s : command not found\n", word[0]);
  492. exit(0);
  493. }
  494. dup2(fd[1], 1);
  495. execvp(word[0], word);
  496. exit(0);
  497. }
  498. if (waitpid(pid2, &status2, 0) == -1)
  499. {
  500. printf("wait for child process error\n");
  501. }
  502. if (!(checkCommand(wordnext[0])))
  503. {
  504. printf("%s : command not found\n", wordnext[0]);
  505. exit(0);
  506. }
  507. dup2(fd[0], 0);
  508. execvp(wordnext[0], wordnext);
  509. exit(0);
  510. }
  511. break;
  512. case 4: //若命令中有&,表示后台执行,父进程直接返回,不等待子进程结束
  513. signal(SIGCHLD, SIG_IGN);
  514. if (pid == 0)
  515. {
  516. //int pidbg;
  517. //pidbg=fork();
  518. //if(pidbg==0){
  519. printf("[process id: %d]\n", pid);
  520. int a = open("/dev/null", O_RDONLY);
  521. dup2(a, 0);
  522. dup2(a, 1);
  523. if (!(checkCommand(word[0])))
  524. {
  525. printf("%s : command not found\n", word[0]);
  526. exit(0);
  527. }
  528. execvp(word[0], word);
  529. exit(0);
  530. //}
  531. }
  532. break;
  533. default:
  534. break;
  535. }
  536. //父进程等待子进程结束
  537. if (waitpid(pid, &status, 0) == -1)
  538. {
  539. printf("wait for child process error\n");
  540. }
  541. }
  542. //查找命令中的可执行程序
  543. int checkCommand(char *command)
  544. {
  545. DIR *dp;
  546. struct dirent *dirp;
  547. char *path[] = {"./", "/bin", "/usr/bin", NULL};
  548. if (strncmp(command, "./", 2) == 0)
  549. {
  550. command = command + 2;
  551. }
  552. //分别在当前目录,/bin和/usr/bin目录查找要执行的程序
  553. int i = 0;
  554. while (path[i] != NULL)
  555. {
  556. if ((dp = opendir(path[i])) == NULL)
  557. {
  558. printf("can not open /bin \n");
  559. }
  560. while ((dirp = readdir(dp)) != NULL)
  561. {
  562. if (strcmp(dirp->d_name, command) == 0)
  563. {
  564. closedir(dp);
  565. return 1;
  566. }
  567. }
  568. closedir(dp);
  569. i++;
  570. }
  571. return 0;
  572. }
  573. void getkinfo()
  574. {
  575. FILE *fp;
  576. if ((fp = fopen("/proc/kinfo", "r")) == NULL)
  577. {
  578. fprintf(stderr, "opening " _PATH_PROC "kinfo failed\n");
  579. exit(1);
  580. }
  581. if (fscanf(fp, "%u %u", &nr_procs, &nr_tasks) != 2)
  582. {
  583. fprintf(stderr, "reading from " _PATH_PROC "kinfo failed\n");
  584. exit(1);
  585. }
  586. fclose(fp);
  587. nr_total = (int)(nr_procs + nr_tasks);
  588. }
  589. int print_memory()
  590. {
  591. FILE *fp;
  592. unsigned int pagesize;
  593. unsigned long total, free, largest, cached;
  594. if ((fp = fopen("/proc/meminfo", "r")) == NULL)
  595. return 0;
  596. if (fscanf(fp, "%u %lu %lu %lu %lu", &pagesize, &total, &free,
  597. &largest, &cached) != 5)
  598. {
  599. fclose(fp);
  600. return 0;
  601. }
  602. fclose(fp);
  603. printf("main memory: %ldK total, %ldK free, %ldK contig free, "
  604. "%ldK cached\n",
  605. (pagesize * total) / 1024, (pagesize * free) / 1024,
  606. (pagesize * largest) / 1024, (pagesize * cached) / 1024);
  607. return 1;
  608. }
  609. void get_procs()
  610. {
  611. struct proc *p;
  612. int i;
  613. p = prev_proc;
  614. prev_proc = proc;
  615. proc = p;
  616. if (proc == NULL)
  617. {
  618. proc = malloc(nr_total * sizeof(proc[0]));
  619. if (proc == NULL)
  620. {
  621. fprintf(stderr, "Out of memory!\n");
  622. exit(1);
  623. }
  624. }
  625. for (i = 0; i < nr_total; i++)
  626. proc[i].p_flags = 0;
  627. parse_dir();
  628. }
  629. void parse_dir()
  630. {
  631. DIR *p_dir;
  632. struct dirent *p_ent;
  633. pid_t pid;
  634. char *end; //end是指向第一个不可转换的字符位置的指针
  635. if ((p_dir = opendir("/proc")) == NULL)
  636. {
  637. perror("opendir on " _PATH_PROC);
  638. exit(1);
  639. }
  640. for (p_ent = readdir(p_dir); p_ent != NULL; p_ent = readdir(p_dir))
  641. {
  642. pid = strtol(p_ent->d_name, &end, 10); //long strtol(char *str, char **endptr, int base)将串转换为长整数,base是基数,表示要转换的是几进制的数
  643. if (!end[0] && pid != 0)
  644. parse_file(pid);
  645. }
  646. closedir(p_dir);
  647. }
  648. void parse_file(pid_t pid)
  649. {
  650. char path[PATH_MAX], name[256], type, state;
  651. int version, endpt, effuid; //版本,端点,有效用户ID
  652. unsigned long cycles_hi, cycles_lo; //高周期,低周期
  653. FILE *fp;
  654. struct proc *p;
  655. //int slot; //插槽?
  656. int i;
  657. //printf("parse_file\n");
  658. sprintf(path, "/proc/%d/psinfo", pid);
  659. if ((fp = fopen(path, "r")) == NULL)
  660. return;
  661. if (fscanf(fp, "%d", &version) != 1)
  662. {
  663. fclose(fp);
  664. return;
  665. }
  666. if (version != PSINFO_VERSION)
  667. { //0
  668. fputs("procfs version mismatch!\n", stderr);
  669. exit(1);
  670. }
  671. if (fscanf(fp, " %c %d", &type, &endpt) != 2)
  672. {
  673. fclose(fp);
  674. return;
  675. }
  676. slot++;
  677. //slot = SLOT_NR(endpt);
  678. if (slot < 0 || slot >= nr_total)
  679. {
  680. fprintf(stderr, "top: unreasonable endpoint number %d\n", endpt);
  681. fclose(fp);
  682. return;
  683. }
  684. p = &proc[slot];
  685. if (type == TYPE_TASK)
  686. p->p_flags |= IS_TASK;
  687. else if (type == TYPE_SYSTEM)
  688. p->p_flags |= IS_SYSTEM;
  689. p->p_endpoint = endpt;
  690. p->p_pid = pid;
  691. if (fscanf(fp, " %255s %c %d %d %lu %*u %lu %lu",
  692. name, &state, &p->p_blocked, &p->p_priority,
  693. &p->p_user_time, &cycles_hi, &cycles_lo) != 7)
  694. {
  695. fclose(fp);
  696. return;
  697. }
  698. strncpy(p->p_name, name, sizeof(p->p_name) - 1);
  699. p->p_name[sizeof(p->p_name) - 1] = 0;
  700. if (state != STATE_RUN)
  701. p->p_flags |= BLOCKED;
  702. p->p_cpucycles[0] = make64(cycles_lo, cycles_hi);
  703. p->p_memory = 0L;
  704. if (!(p->p_flags & IS_TASK))
  705. {
  706. int j;
  707. if ((j = fscanf(fp, " %lu %*u %*u %*c %*d %*u %u %*u %d %*c %*d %*u",
  708. &p->p_memory, &effuid, &p->p_nice)) != 3)
  709. {
  710. fclose(fp);
  711. return;
  712. }
  713. p->p_effuid = effuid;
  714. }
  715. else
  716. p->p_effuid = 0;
  717. for (i = 1; i < CPUTIMENAMES; i++)
  718. {
  719. if (fscanf(fp, " %lu %lu",
  720. &cycles_hi, &cycles_lo) == 2)
  721. {
  722. p->p_cpucycles[i] = make64(cycles_lo, cycles_hi);
  723. }
  724. else
  725. {
  726. p->p_cpucycles[i] = 0;
  727. }
  728. }
  729. if ((p->p_flags & IS_TASK))
  730. {
  731. if (fscanf(fp, " %lu", &p->p_memory) != 1)
  732. {
  733. p->p_memory = 0;
  734. }
  735. }
  736. p->p_flags |= USED;
  737. fclose(fp);
  738. }
  739. u64_t cputicks(struct proc *p1, struct proc *p2, int timemode)
  740. {
  741. int i;
  742. u64_t t = 0;
  743. for (i = 0; i < CPUTIMENAMES; i++)
  744. {
  745. if (!CPUTIME(timemode, i))
  746. continue;
  747. if (p1->p_endpoint == p2->p_endpoint)
  748. {
  749. t = t + p2->p_cpucycles[i] - p1->p_cpucycles[i];
  750. }
  751. else
  752. {
  753. t = t + p2->p_cpucycles[i];
  754. }
  755. }
  756. return t;
  757. }
  758. void print_procs(struct proc *proc1, struct proc *proc2, int cputimemode)
  759. {
  760. int p, nprocs;
  761. //u64_t idleticks = 0;
  762. //u64_t kernelticks = 0;
  763. u64_t systemticks = 0;
  764. u64_t userticks = 0;
  765. u64_t total_ticks = 0;
  766. int blockedseen = 0;
  767. static struct tp *tick_procs = NULL; //tp结构体的数组tick_procs,对所有的进程和任务(即上面读出来的nr_total)计算ticks
  768. if (tick_procs == NULL)
  769. {
  770. tick_procs = malloc(nr_total * sizeof(tick_procs[0]));
  771. if (tick_procs == NULL)
  772. {
  773. fprintf(stderr, "Out of memory!\n");
  774. exit(1);
  775. }
  776. }
  777. for (p = nprocs = 0; p < nr_total; p++)
  778. {
  779. u64_t uticks;
  780. if (!(proc2[p].p_flags & USED))
  781. continue;
  782. tick_procs[nprocs].p = proc2 + p;
  783. tick_procs[nprocs].ticks = cputicks(&proc1[p], &proc2[p], cputimemode);
  784. uticks = cputicks(&proc1[p], &proc2[p], 1);
  785. total_ticks = total_ticks + uticks;
  786. //printf("total_ticks:%llu\n",total_ticks);
  787. /*if(p-NR_TASKS == IDLE) {
  788. idleticks = uticks;
  789. continue;
  790. }
  791. if(p-NR_TASKS == KERNEL) {
  792. kernelticks = uticks;
  793. }
  794. */
  795. if (!(proc2[p].p_flags & IS_TASK))
  796. {
  797. if (proc2[p].p_flags & IS_SYSTEM)
  798. systemticks = systemticks + tick_procs[nprocs].ticks;
  799. else
  800. userticks = userticks + tick_procs[nprocs].ticks;
  801. }
  802. nprocs++;
  803. }
  804. if (total_ticks == 0)
  805. return;
  806. printf("CPU states: %6.2f%% user, ", 100.0 * userticks / total_ticks);
  807. printf("%6.2f%% system", 100.0 * systemticks / total_ticks);
  808. printf("%6.2f%% in total\n", 100.0 * (systemticks + userticks) / total_ticks);
  809. //printf("%6.2f%% kernel, ", 100.0 * kernelticks/ total_ticks);
  810. //printf("%6.2f%% idle", 100.0 * idleticks / total_ticks);
  811. }