进程(3)

                                     linux系统中进程的组织方式

         一个系统中通常可以有数百个数千个进程,相应的也就有这么多的PCB,必须使用一些适当的方式将这些PCB组织起来。进程的组织方式其实大都是数据结构中数据的组织方式。

         进程链表:双向循环链表将进程联系起来

         struct task_struct

         {

              struct list_head tasks;

              char comm[TASK_COM_LEN];//可执行程序的名字带路径

         }

          链表的头和尾都是init_task,0号进程的PCB,这个进程永远不会被撤销他被静态分配在内核数据段中。

          哈希表:有些情况根据进程的PID导出对应的PCB,顺序扫描效率低下。于是引入哈希表。

          linux用一个宏pid_hashfn()将PID转换成表的索引。通过pid_hashfn()可以把进程的PID均匀的散列在哈希表中。给定一个PID寻找其对应的PCB函数

          static inline struct task_struct * find_task_by_pid(int pid)

          {

                 struct task_struct *p, **htable = &pidhash[pid_hashfn()];

                 for(p = *htable; p && p->pid != pid; p = pidhash->next)

                           return p;

 

          }

          pidhash是哈希表,其定义为struct task_struct *pidhash[PIDHASH_SZ];

          哈希函数并不能保证PID与表的索引一一对应,因此两个不同的PID散列到相同的索引上引起冲突,采用链地址法来处理冲突的PID。也就是说每一个表项是由冲突的PID组成的双休链表。task_struct 结构中有两个域pidhash_next和pidhash_prev来实现这个链表,同一链中的PID由小向大排列。

          就绪队列:把所有可运行状态的进程组成一个双向链表叫做就绪队列

          struct task_struct{

               struct list_head run_list;

               ,,,

          }

          就绪队列的定义及相关操作在/kernel/sched.c文件中

          static LIST_HEAD(runqueue_head);//定义就绪队列的头指针为runqueue_head

          static inline void add_to_runqueue(struct task_struct *p)

          {

                 list_add_tail(&p->run_list, &runqueue_head);

                 nr_running++;

          }

          static inline void move_last_runqueue(struct task_struct *p)

          {

                  list_del(&p->run_list);

                  list_add_tail(&p->run_list, &runqueue_head);

          }

          等待队列:深度睡眠和浅度睡眠两种状态的进程位于同一个等待队列上,等待某些事件不能运行。

等待队列的数据结构

          struct __wait_queue

          {

                unsigned int flags;

                #define WQ_FLAG_EXCLUSIVE 0x01

                void * private;

                wait_queue_func_t func;

                struct list_head task_list;

          };

            typedef struct __wait_queue wait_queue_t;

            typedef int (*wait_queue_func_t)(wait_queue_t *wait, unsigned mode, int flags, void *key);

          task_list把处于睡眠状态的进程连接成双向链表。睡眠是暂时的唤醒才是目的,设置了func域,该域指向唤醒函数,用于吧队列中的进程唤醒。flags域为了区分睡眠时的互斥进程(1)和非互斥进程(0)。private域是传递给func函数的参数。

等待队列头

        struct __wait_queue_head

       {

                spinlock_t lock;

                struct list_head task_list;

       };

       typedef struct __wait_queue_head wait_queue_head_t;

       等待队列是由中断处理程序和主要的内核函数修改的,因此必须对其双向链表进行保护以免同时访问,通过lock自旋锁进行同步,task_list域是等待进程链表的头

      

             

          

 

      

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值