Before looking at the Linux PCI device initialization, see a bit dizzy, and then hand-over the notes written before, at the same time rest!! ~(@^_^@)~
This piece of article is written before, which refer to some of the blog of the Daniel!!
the design of PID frame
The design of a framework takes many factors into account, and it is believed that readers who have analyzed the Linux kernel will find that a large number of data structures of the kernel are connected by hash tables and chain tables, and the most important purpose is to find them. Imagine a good framework, you should take into account the speed of retrieval, but also consider the division of functions. There are several factors that need to be considered in the PID framework.
How to quickly find the corresponding PID via task_struct
How to find the corresponding task_struct quickly by PID
How to quickly assign a unique PID
These are some of the basic factors that need to be considered when designing a PID framework. It is these factors that will complicate the design of the PID framework.
the original PID frame
Consider the simple point first, a process corresponding to a PID
struct Task_struct {
... ..
pid_t pid;
... ..
}
Introducing Hlist and PID bitmaps
struct task_struct *PIDHASH[PIDHASH_SZ];
This is very convenient, and then look at the PID framework design some of the factors are satisfied, how to assign a unique PID, continuous increment? , then the assigned PID will need to be reclaimed until the maximum value of the PID is assigned, and then continue from the beginning if the previously assigned process is finished. Well, this may be a good idea, but is it necessary to mark those PID to be available? This seems like a solution, but given that the solution is to be put into the kernel, the guys who develop Linux will certainly want to optimize it in nearly any way, and, indeed, they use a PID bitmap, But the basic idea has not changed, also need to mark the PID is usable, but uses the PID bitmap the way to save the memory more. Imagine that by setting each bit to 0 or 1, it can be used to indicate whether it is available, and the 1th bit of 0 and 1 is used to indicate whether the PID is 1 usable. And so on. To this end a seemingly good PID framework design is completed, is the overall effect of the whole framework at present.
Use the introduction of Daniel above to introduce today's theme:
In fact, the benefits of PID namespace far more than this, the most important of which is the support of lightweight virtualization. The current hot Docker is based on the principle of namespaces in the Linux kernel. With the PID namespace, we can guarantee the isolation of the process, at least in the process of the point of view, can be organized in accordance with the namespace way, different namespace processes do not interfere with each other. This is also the author to analyze the underlying virtualization support one of the original intention!
Anyway
PID Framework after introduction of process PID namespace
As the kernel continues to add new kernel features, especially the introduction of the PID namespace mechanism, which leads to the concept of a namespace in the PID, and the concept of a hierarchy of namespaces exists, the high level can be seen by the lower level, which leads to high-level processes with multiple PID, For example, under the default namespace, a new namespace is created, which is called Level1, and the default namespace is called Level0, which runs a process in level1 with a PID of 1 in Level1 because the high-level PID Namespace need to be seen by the low-level PID namespace, so this process in level0 will have another PID, for XXX. Use the concept of the PID bitmap mentioned above, imagine, for each PID namespace should have a pidmap, the Level1 process mentioned above has two PID one is 1, the other is xxx, where PID is 1 is in the Level1 pidmap to allocate, PID is assigned in Level0 Pidmap. The picture below is a frame of the whole pidnamespace.
You can see that there is a hierarchy in which a namespace can have its child namespaces, and the processes in the child namespaces also appear in the parent namespace, except that the process IDs are different. Look at the structure of the PID:
1 structPID2 {3 atomic_t count;4UnsignedintLevel ;5 /*lists of the tasks that use the This PID*/6 structHlist_head Tasks[pidtype_max];7 structrcu_head RCU;8 structUpid numbers[1];9};
Count represents this PID reference count, the same PID structure can be shared by multiple processes;
Level indicates the hierarchy at which the PID is located;
Tasks is a hash array, and each item is a list header. respectively, PID link table header, Process Group ID table header, session ID table header;
RCU is used to protect pointer references;
Numbers is a upid array that records the Upid in the namespace of the corresponding hierarchy, so it can be thought that the PID is in the first layer, then the array should have several items (all starting from 0, of course).
Look at the UPID structure:
1 struct upid {2 /* */3 int nr; 4 struct pid_namespace *NS; 5 struct Hlist_node Pid_chain; 6 };
Upid is a lot simpler than that, or that's the real PID.
NR denotes ID number;
Namespace points to the namespace structure of the Upid's namespace;
Pid_chain is a linked list, the system will upid nr and namespace NS through some kind of hash, get in a global hash array subscript, this upid will be added to the corresponding subscript list.
See how the PID is applied in the process:
1 struct task_struct{2 ... 3 struct Pid_link Pids[pidtype_max]; 4 ... 5 }
The process contains an array of pid_link structures, so let's look at a pid_link structure first:
1 struct Pid_link 2 {3 struct hlist_node node; 4 struct pid *pid; 5 };
Nodes are added as a node to all process lists that reference the same PID structure;
PID points to the PID structure referenced by the process.
Maybe it's a bit of a disorder to be here, so take a look at the following figure:
Yes, I painted this picture!! Haha, it can take me a lot of time, I hope to understand the process structure and PID and upid relationship between the help. There is nothing to explain when you post this diagram, which has been shown in various diagrams. However, it is important to note that the bottom of the upid I just use a box to represent, in fact, numbers point to upid structure, and let Upid join the list is the structure of pid_chain; Another problem is that upid that group of linked lists is not the same PID of all the upid, according to the kernel source code, here is just a way to deal with the conflict, and here the list is only to indicate that this is a linked list exists.
The following is the PID bitmap:
Each namespace corresponds to a map that is used to assign the PID number. This contains two members, Nr_free represents the number of available ID numbers, and the second is a pointer to a page. So the design has its own rationality. By default, page points to a page, and a page is the size of 4KB, that is, 4,096 bytes, that is, 4096*8bit, each one represents a PID number, a page can represent 32,768 process ID, the general situation is absolutely enough, even if the special situation is not enough, Then it can be extended dynamically, and that's where it's justified.
1 struct Pidmap {2 atomic_t nr_free; 3 void *page; 4 };
Here is the PID_NAMESPACE structure:
1 structPid_namespace {2 structkref kref;3 structPidmap Pidmap[pidmap_entries];//pid bitmap corresponding to the namespace4 intLast_pid;//last assigned PID for next assignment5Unsignedintnr_hashed;6 structTask_struct *Child_reaper;7 structKmem_cache *Pid_cachep;8UnsignedintLevel//The hierarchy at which the namespace resides9 structPid_namespace *parent;//pointer to parent namespaceTen #ifdef CONFIG_PROC_FS One structVfsmount *proc_mnt; A structDentry *proc_self; - #endif - #ifdef CONFIG_BSD_PROCESS_ACCT the structBsd_acct_struct *Bacct; - #endif - structUser_namespace *User_ns; - structwork_struct proc_work; + kgid_t Pid_gid; - intHide_pid; + intReboot/*Group Exit code if this pidns is rebooted*/ AUnsignedintProc_inum; at};
The next section will be based on the Linux kernel source code analysis of the specific PID allocation situation
Namespace PID namespace in Linux kernel