操作系统实验:实现pstree命令第二步(根据已知的pid和ppid构建链表,方便第三步打印进程树)

这篇博客介绍了一种使用单链表结构来表示进程树的方法,通过`PROC`和`CHILD`结构体存储进程及其子进程信息。文章提供了一个`add_proc`函数,用于根据进程名、PID和PPID动态添加进程到链表中,并连接父子进程关系。在测试中,展示了如何遍历并打印出进程树的信息,包括每个进程的PID、名字、父进程的名称以及子进程列表。
摘要由CSDN通过智能技术生成

该部分的实验思路来自:read://https_rivers-shall.github.io/?url=https%3A%2F%2Frivers-shall.github.io%2F2019%2F03%2F05%2FNJU-OS-M1-pstree%2F

第一部分已经完成的工作

第一部分我们从/proc中读取了进程id和其父进程ppid,并将其信息存储在了数组中。

这一部分要为打印进程树创建相应的数据结构

要打印进程树我们需要知道每个进程的父进程,要知道每个进程的孩子进程。仅仅使用第一部分我们使用的简单数组的结构也可以实现这部分功能,但是我们可以使用一种更为高效的数据结构。
![在这里插入图片描述](https://img-blog.csdnimg.cn/41c42bf63b834e6c8a021562c675160b.png#pic_center)

相应的结构体定义

typedef struct proc{
    struct proc *next;
    struct proc *parent;
    struct child *children;
    int pid;
    char pName[50];
}PROC;
typedef struct child{
    const PROC* proc;
    struct child *next;
}CHILD;

构建相应数据结构的思路

我们使用单链表来存储进程的信息,在加入一个进程时,由于我们知道其父进程的pid,同时可以将其父进程也加入进程链表。在后面再扫描到其父进程时,我们再完善其父进程的信息(如父进程的名字)

PROC* add_proc(const char* name,int pid,int ppid)
{
    PROC *this=find_proc(pid);
/*    
    if(this==NULL)
    {
        printf("dont find process %d %s in the list\n",pid,name);
    }else
    {
        printf(" the process %d %s in the list\n",pid,name);
    }
*/
    if(this!=NULL)//该进程已被加入队列
    {
        rename_proc(this,name);
    }else
    {
        this=new_proc(name,pid);
        if(this==NULL)
        {
            printf("new_proc error!\n");
        }
        this->next=list;
        list=this;
    }

    if(ppid==-1)
    {
       // printf("没有父进程,退出!\n");
        return this;//0号进程没有父进程,无需处理
    }
    //处理其父进程
    PROC* parent=find_proc(ppid);
    if(parent==NULL)
    {
        parent=new_proc("?",ppid);
    /*
        if(parent==NULL)
        {
            printf("add parent %d error!\n",ppid);
        }else
        {
            printf("creat parent %d  %s\n",ppid,parent->pName);
        }
    */
        parent->next=list;
        list=parent;
    }

    this->parent=parent;
    add_child(parent,this);

    return this;
}

对于add_proc中使用到的一些函数,大家可以尝试自己实现一下。

int main()
{
    
    char* name[8]={"(0)","(one one)","((twotwotwo))","(3333)","(4444)","(five)(five)","(sixsix)()","777777"};

    add_proc(name[0],0,-1);//0号进程没有父进程
   // add_proc("0",0,-1);
    add_proc(name[1],1,-1);
    add_proc(name[2],2,1);
    add_proc(name[3],3,1);
    add_proc(name[4],4,2);
    add_proc(name[5],5,2);
    add_proc(name[6],6,3);
    add_proc(name[7],7,4);
/*
    PROC *cur=list;
    while(cur!=NULL)
    {
        printf("%d  %s\n",cur->pid,cur->pName);
        if(cur->parent==NULL)
        {
            printf("do not have parent\n");
        }
        cur=cur->next;
    }
    */
    travel(list);
   
    return 0;
}

相应的测试结果

pid:7  name:777777    ppid:4     parentName:(4444)
i dont have children!

pid:6  name:(sixsix)()    ppid:3     parentName:(3333)
i dont have children!

pid:5  name:(five)(five)    ppid:2     parentName:((twotwotwo))
i dont have children!

pid:4  name:(4444)    ppid:2     parentName:((twotwotwo))
my children:    pid:7  pname:777777    

pid:3  name:(3333)    ppid:1     parentName:(one one)
my children:    pid:6  pname:(sixsix)()    

pid:2  name:((twotwotwo))    ppid:1     parentName:(one one)
my children:    pid:5  pname:(five)(five)    pid:4  pname:(4444)    

pid:1  name:(one one)    i dont have parent
my children:    pid:3  pname:(3333)    pid:2  pname:((twotwotwo))    

pid:0  name:(0)    i dont have parent
i dont have children!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值