读书笔记-深入linux内核架构-Chapter 2 - part1

《第二章》进程管理和调度

 主流的Linux内核不支持硬实时,但一些修改版本如RTLinuxXenomaiRATI。在这些修改方案中,Linux内核作为独立进程运行,实时的工作在内核外部完成,只有当没有实时操作的时候,内核才会运行。

 2.5内核中引入了O(1)的调度算法,2.6.23时引入完全公平调度器(CFS)。

 命名空间

 命名空间建立了系统的不同视图,此前的每一项全局资源都必须包装到容器数据结构中,只有资源和包含该资源的命名空间组成的二元组仍然是全局唯一的。

clip_image002

新的命名空间的创建:

1. fork或者clone时,可以设定是与父进程共享命名空间还是创建新的命名空间;

2. unshare系统调用将进程的某些部分从父进程分离出来,其中包括命名空间。

 命名空间的实现:

1.每个子系统的命名空间结构;

2.将给定进程关联到所属各个命名空间的机制。

 每个子系统的命名空间结构

 struct nsproxy {

     atomic_t count;

     struct uts_namespace *uts_ns;

     struct ipc_namespace *ipc_ns;

     struct mnt_namespace *mnt_ns;

     struct pid_namespace *pid_ns;

 struct user_namespace *user_ns;

 struct net *net_ns;

 };

 UTS命名空间

 struct uts_namespace {

 struct kref kref;

 struct new_utsname name;

 };

 struct new_utsname {

   char sysname[65];

   char nodename[65];

   char release[65];

   char version[65];

   char machine[65];

   char domainname[65];

 };

 用户命名空间

 struct user_namespace {

   struct kref kref;

   struct hlist_head uidhash_table[UIDHASH_SZ];

   struct user_struct *root_user;

 };

 pid命名空间

 某些进程具有多个pid(凡是可以看见该进程的命名空间都得分一个pid给它),数据结构要反映出局部pid和全局pid。全局pid指在内核本身和初始命名空间(init进程所在的命名空间)唯一的pid,局部pid指特定命名空间中中该进程的pidtask_struct中保存的pidtgid是全局pid和线程组ID

 

clip_image004

struct pid_namespace {

       ...

     //相当于全局的init进程,用来对孤儿进程调用wait4

       struct task_struct *child_reaper

     ...

      intlevel;//该命名空间的层次

       struct pid_namespace *parent;//父命名空间

 };

 pid的管理围绕两个数据结构展开---struct upidstruct pid

 struct upid { //对特定命名空间课件的pid信息

     int nr;    // ID数值

     struct pid_namespace *ns;   //ID所属的命名空间

     struct hlist_node pid_chain;    //所有的upid放在散列表pid_chain中。

 };

 struct pid { //内核对pid的内部表示

     atomic_t count;

     /* 使用该pid的进程列表的数组。*/

     struct hlist_head tasks[PIDTYPE_MAX];

     intlevel;    //层次。

     struct upid numbers[1];     //可以再附加元素。

 };

 

struct task_struct {

 /* PID/PID hash table linkage. */

   struct pid_link pids[PIDTYPE_MAX];

   ...

 };

 

struct pid_link{

   struct hlist_node node;

   struct pid *pid;

 };

 

两个操作:

  (1)   给出task_struct和命名空间,取得局部ID

  (2)   给出局部ID和命名空间,查找task_struct

 操作(1)的过程:

 staticinlinestruct pid *task_pid(struct task_struct *task){

   return task->pids[PIDTYPE_PID].pid; /* Error?! */

 }

 pid_t pid_nr_ns(struct pid *pid, struct pid_namespace *ns) {

   struct upid *upid;

   pid_t nr = 0;

   if (pid && ns->level <= pid->level) {

     upid = &pid->numbers[ns->level];

      if (upid->ns == ns)

         nr = upid->nr;

   }

   return nr;

 }

 

pid_t task_pid_nr_ns(struct task_struct *tsk, struct pid_namespace *ns);

  

操作(2)的过程(内核如何将数字PID和命名空间转换为pid实例):

 

clip_image006

 

 struct upid按数字PID和命名空间映射存储,当给定数字PID和命名空间时,可以获取struct upid,然后根据container_of获取struct pidstruct pid中的tasks字段的第一个task_struct

 PID的分配使用位图。

 进程关系:

 

 

clip_image008

 

  struct task_struct {

     ...

     struct list_head children; /* list of my children */

     struct list_head sibling; /* linkage in my parent’s children list */

     ...

 }

 

将给定进程关联到所属各个命名空间的机制

 struct task_struct {

     ...

     /* namespaces */

     struct nsproxy *nsproxy;

     ...

 }

 

你可能感兴趣的:(linux)