@Lxjeng
2016-04-10T07:41:35.000000Z
字数 3645
阅读 913
- 姓名:梁晓静 学号:1405010530 班级:计算机5班
- 报告提交日期:2016.4.11 报告提交截止日期:2016.4.11
- 1、在Linux环境下,用c语音编写一个程序,以树状结构(即体现父子关系)输出系统当前所有进程。
- 2、修改do_fork函数,使用printk函数输出do_fork函数执行过程信息到日志。
- 1.理解进程和程序、进程和线程的联系与区别;
- 2.熟悉进程的重要数据结构、进程的状态、进程的管理与控制及实现机制;
- 3.练习获取进程执行的相关信息,理解进程的执行过程。
- 一台装有 Ubuntu 的计算机。
- 在 Linux 下,用 C 语言自己编写一个程序,要求能以树状结构(即能体 现父子关系)打印出系统当前的所有进程;
- 重新编译内核,到源码fork.c中修改do_fork函数,调用printk函数输出程信息到日志。最后运行给定代码forktest.c,同时用另一个终端运行命令“tail-f/var/log/messages”观察输出信息。
- 本实验通过采用在用户态运行 C 程序来打印进程树。Ubuntu系统的/proc 目 录下有一组以进程号pid为目录名的文件,每个目录包含了进程的具体信息,于是通过/proc目录获得各进程的父进程ppid,获得进程树的父亲表示,再将进程树的父亲表示转换成左孩子与右孩子,最后中序遍历二叉树,输出进程信息即可。
①创建pstree.c文件;

查看进程树的命令 pstree
②用 gcc工具编译源文件;
- $gcc –o pstree pstree.c
③运行编译好的可执行文件。
- $./pstree
实验运行结果如图所示

实验过程遇到的问题:
这些都是因为写程序的时候,粗心写错了几个地方,然后又仔仔细细对照源码改的,然而运行后...

- 这是乱码了么... 问了同学,说是代码错了,可是我又对照了一遍
并没有错。所以复制粘贴了别人的就可以了...
#include <unistd.h>#include <stdio.h>int main (){pid_t fpid;int count=0;fpid=fork();if (fpid < 0)printf("error in fork!");else if (fpid == 0) {printf("i am the child process, my process id is %d/n",getpid());count++;}else {printf("i am the parent process, my process id is %d/n",getpid());count++;}printf("统计结果是: %d/n",count);return 0;}
找到fork.c并修改do_fork函数

- 本实验的两个关键问题是如何得到系统进程树1号进程信息,如何由1号进程开始获取所以进程关联关系。解决途径是访问/proc目录,目录下有一组以进程号pid为目录名的文件,每个目录包含了进程的具体信息,于是通过/proc 目录获得各进程的父进程ppid,获得进程树的父亲表示,再将进程树的父亲表示转换成左孩子与右孩子,最后中序遍历二叉树,输出进程信息。
- 通过本次实验,我熟悉了Linux系统下进程和线程的联系和区别,及线程的创建和调用。由于不知道怎么修改do_fork函数,所以第二个实验并没有完成,问了老师但并没有回,而且班上也没人会, 虽然这都是借口。
#include<stdio.h>#include <stdlib.h>#include <errno.h>#include <string.h>#include <sys/types.h>#include <stdlib.h>#include <errno.h>#include <netdb.h>#include <sys/types.h>#include <pthread.h>#include <unistd.h>#include <dirent.h>char default_path[1024]="/proc/";int s=0;typedef struct file_info{int pid; // 进程号int ppid; // 父进程号char name[1024]; // 进程名称int flag; // 进程标志int rec; // 打印进程树时用来标记是几级进程的}info;int my_getpid(char *str)//获得进程号{int len=strlen(str); char num[10]; int i,j,ret;if(strncmp(str,"Pid",3)==0){ for(i=0;i<len;i++){if(str[i]>='0'&&str[i]<='9')break;}for(j=0;j<len-i;j++)num[j]=str[i+j];ret=atoi(num);}else ret=0;return ret;}int my_getppid(char *str) // 获得父进程号{int len=strlen(str);char num[10];int i,j,ret;if(strncmp(str,"PPid",4)==0){for(i=0;i<len;i++){if(str[i]>='0'&&str[i]<='9')break;}for(j=0;j<len-i;j++)num[j]=str[i+j];ret=atoi(num);}else ret=0;return ret;}int child_exist(info *file,int count,int ppid) //判断是否存在子进程{int i;for(i=0;i<count;i++){if(file[i].flag==0&&file[i].ppid==ppid) return 1;}return 0;}void print_pstree(info *file,int count,int ppid,int rec)//打印进程树,用递归方法,中序遍历{int i,j,k;for(i=0;i<count;i++){if(file[i].flag==0&&file[i].ppid==ppid){file[i].rec=rec+1;file[i].flag=1;for(k=0;k<rec;k++) printf("-");printf("%s\n",file[i].name);print_pstree(file,count,file[i].pid,file[i].rec);}}}int main(){int i,j,k,total,s1,s2,count,t;char str[1024],dir[1024];struct dirent **namelist;strcpy(dir,default_path);total = scandir(dir, &namelist, 0, alphasort);printf("path=%s,total=%d\n",dir,total);for(i=0;i<total;i++){strcpy(str,namelist[i]->d_name);if(str[0]>='0'&&str[0]<='9')count++;}printf("进程数:%d\n",count);info file[1024];i=0;t=0;while(i<total){FILE *fp;char path[1024],name[1024];int pid,ppid;strcpy(str,namelist[i]->d_name);strcpy(path,default_path);if(str[0]>='0'&&str[0]<='9'){strcat(path,str);strcat(path,"/status");fp=fopen(path,"r");while(!feof(fp)){fgets(str,1024,fp);//pidif((s1=my_getpid(str))!=0)pid=s1;//ppidif((s2=my_getppid(str))!=0)ppid=s2;//nameif(strncmp(str,"Name",4)==0){for(j=4;j<strlen(str);j++){if(str[j]>='a'&&str[j]<='z')break;}for(k=j;k<strlen(str);k++)name[k-j]=str[k];name[k-j-1]='\0';}file[t].pid=pid;file[t].ppid=ppid;strcpy(file[t].name,name);}fclose(fp);t++;}i++;}memset(&file->flag,0,count);memset(&file->rec,0,count);print_pstree(file,count,0,0);}