Next Previous Contents2. Process and Interrupt Management2.1 Task Stru dịch - Next Previous Contents2. Process and Interrupt Management2.1 Task Stru Việt làm thế nào để nói

Next Previous Contents2. Process an

Next Previous Contents
2. Process and Interrupt Management

2.1 Task Structure and Process Table

Every process under Linux is dynamically allocated a struct task_struct structure. The maximum number of processes which can be created on Linux is limited only by the amount of physical memory present, and is equal to (see kernel/fork.c:fork_init()):

/*
* The default maximum number of threads is set to a safe
* value: the thread structures can take up at most half
* of memory.
*/
max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 2;
which, on IA32 architecture, basically means num_physpages/4. As an example, on a 512M machine, you can create 32k threads. This is a considerable improvement over the 4k-epsilon limit for older (2.2 and earlier) kernels. Moreover, this can be changed at runtime using the KERN_MAX_THREADS sysctl(2), or simply using procfs interface to kernel tunables:

# cat /proc/sys/kernel/threads-max
32764
# echo 100000 > /proc/sys/kernel/threads-max
# cat /proc/sys/kernel/threads-max
100000
# gdb -q vmlinux /proc/kcore
Core was generated by `BOOT_IMAGE=240ac18 ro root=306 video=matrox:vesa:0x118'.
#0 0x0 in ?? ()
(gdb) p max_threads
$1 = 100000
The set of processes on the Linux system is represented as a collection of struct task_struct structures which are linked in two ways:

as a hashtable, hashed by pid, and
as a circular, doubly-linked list using p->next_task and p->prev_task pointers.
The hashtable is called pidhash[] and is defined in include/linux/sched.h:

/* PID hashing. (shouldnt this be dynamic?) */
#define PIDHASH_SZ (4096 >> 2)
extern struct task_struct *pidhash[PIDHASH_SZ];

#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
The tasks are hashed by their pid value and the above hashing function is supposed to distribute the elements uniformly in their domain (0 to PID_MAX-1). The hashtable is used to quickly find a task by given pid, using find_task_pid() inline from include/linux/sched.h:

static inline struct task_struct *find_task_by_pid(int pid)
{
struct task_struct *p, **htable = &pidhash[pid_hashfn(pid)];

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

return p;
}
The tasks on each hashlist (i.e. hashed to the same value) are linked by p->pidhash_next/pidhash_pprev which are used by hash_pid() and unhash_pid() to insert and remove a given process into the hashtable. These are done under protection of the read-write spinlock called tasklist_lock taken for WRITE.

The circular doubly-linked list that uses p->next_task/prev_task is maintained so that one could go through all tasks on the system easily. This is achieved by the for_each_task() macro from include/linux/sched.h:

#define for_each_task(p)
for (p = &init_task ; (p = p->next_task) != &init_task ; )
Users of for_each_task() should take tasklist_lock for READ. Note that for_each_task() is using init_task to mark the beginning (and end) of the list - this is safe because the idle task (pid 0) never exits.

The modifiers of the process hashtable or/and the process table links, notably fork(), exit() and ptrace(), must take tasklist_lock for WRITE. What is more interesting is that the writers must also disable interrupts on the local CPU. The reason for this is not trivial: the send_sigio() function walks the task list and thus takes tasklist_lock for READ, and it is called from kill_fasync() in interrupt context. This is why writers must disable interrupts while readers don't need to.

Now that we understand how the task_struct structures are linked together, let us examine the members of task_struct. They loosely correspond to the members of UNIX 'struct proc' and 'struct user' combined together.

The other versions of UNIX separated the task state information into one part which should be kept memory-resident at all times (called 'proc structure' which includes process state, scheduling information etc.) and another part which is only needed when the process is running (called 'u area' which includes file descriptor table, disk quota information etc.). The only reason for such ugly design was that memory was a very scarce resource. Modern operating systems (well, only Linux at the moment but others, e.g. FreeBSD seem to improve in this direction towards Linux) do not need such separation and therefore maintain process state in a kernel memory-resident data structure at all times.

The task_struct structure is declared in include/linux/sched.h and is currently 1680 bytes in size.

The state field is declared as:

volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */

#define TASK_RUNNING 0
#define TASK_INTERRUPTIBLE 1
#define TASK_UNINTERRUPTIBLE 2
#define TASK_ZOMBIE 4
#define TASK_STOPPED 8
#define TASK_EXCLUSIVE 32
Why is TASK_EXCLUSIVE defined as 32 and not 16? Because 16 was used up by TASK_SWAPPING and I forgot to shift TASK_EXCLUSIVE up when I removed all references to TASK_SWAPPING (sometime in 2.3.x).

The volatile in p->state declaration means it can be modified asynchronously (from interrupt handler):

TASK_RUNNING: means the task is "supposed to be" on the run queue. The reason it may not yet be on the runqueue is that marking a task as TASK_RUNNING and placing it on the runqueue is not atomic. You need to hold the runqueue_lock read-write spinlock for read in order to look at the runqueue. If you do so, you will then see that every task on the runqueue is in TASK_RUNNING state. However, the converse is not true for the reason explained above. Similarly, drivers can mark themselves (or rather the process context they run in) as TASK_INTERRUPTIBLE (or TASK_UNINTERRUPTIBLE) and then call schedule(), which will then remove it from the runqueue (unless there is a pending signal, in which case it is left on the runqueue).
TASK_INTERRUPTIBLE: means the task is sleeping but can be woken up by a signal or by expiry of a timer.
TASK_UNINTERRUPTIBLE: same as TASK_INTERRUPTIBLE, except it cannot be woken up.
TASK_ZOMBIE: task has terminated but has not had its status collected (wait()-ed for) by the parent (natural or by adoption).
TASK_STOPPED: task was stopped, either due to job control signals or due to ptrace(2).
TASK_EXCLUSIVE: this is not a separate state but can be OR-ed to either one of TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE. This means that when this task is sleeping on a wait queue with many other tasks, it will be woken up alone instead of causing "thundering herd" problem by waking up all the waiters.
Task flags contain information about the process states which are not mutually exclusive:

unsigned long flags; /* per process flags, defined below */
/*
* Per process flags
*/
#define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */
/* Not implemented yet, only for 486*/
#define PF_STARTING 0x00000002 /* being created */
#define PF_EXITING 0x00000004 /* getting shut down */
#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */
#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */
#define PF_DUMPCORE 0x00000200 /* dumped core */
#define PF_SIGNALED 0x00000400 /* killed by a signal */
#define PF_MEMALLOC 0x00000800 /* Allocating memory */
#define PF_VFORK 0x00001000 /* Wake up parent in mm_release */
#define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */
The fields p->has_cpu, p->processor, p->counter, p->priority, p->policy and p->rt_priority are related to the scheduler and will be looked at later.

The fields p->mm and p->active_mm point respectively to the process' address space described by mm_struct structure and to the active address space if the process doesn't have a real one (e.g. kernel threads). This helps minimise TLB flushes on switching address spaces when the task is scheduled out. So, if we are scheduling-in the kernel thread (which has no p->mm) then its next->active_mm will be set to the prev->active_mm of the task that was scheduled-out, which will be the same as prev->mm if prev->mm != NULL. The address space can be shared between threads if CLONE_VM flag is passed to the clone(2) system call or by means of vfork(2) system call.

The fields p->exec_domain and p->personality relate to the personality of the task, i.e. to the way certain system calls behave in order to emulate the "personality" of foreign flavours of UNIX.

The field p->fs contains filesystem information, which under Linux means three pieces of information:

root directory's dentry and mountpoint,
alternate root directory's dentry and mountpoint,
current working directory's dentry and mountpoint.
This structure also includes a reference count because it can be shared between cloned tasks when CLONE_FS flag is passed to the clone(2) system call.

The field p->files contains the file descriptor table. This too can be shared between tasks, provided CLONE_FILES is specified with clone(2) system call.

The field p->sig contains signal handlers and can be shared between cloned tasks by means of CLONE_SIGHAND.

2.2 Creation and termination of tasks and kernel threads

Different books on operating systems define a "process" in different ways, starting from "instance of a program in execution" and ending with "that which is produced by clone(2) or fork(2) system calls". Under Linux, there are three kinds of processes:

the idle thread(s),
kernel threads,
user tasks.
The idle thread is created at compile time for the first CPU; it is then "manually" created for each CPU by means of arch-specific fork_by_hand() in arch/i386/kernel/smpboot.c, which unrolls the fork(2) system call by hand (on some archs). Idle tasks share one init_task structure but have a private TSS structure, in the per-CPU array init_tss. Idle tasks all have pid = 0 and no other task can
0/5000
Từ: -
Sang: -
Kết quả (Việt) 1: [Sao chép]
Sao chép!
Nội dung trước đó tiếp theo2. quá trình và làm gián đoạn quản lý2.1 công việc cấu trúc và quá trình bảngMỗi quá trình dưới Linux tự động được cấp phát một cấu trúc task_struct struct. Số quy trình mà có thể được tạo ra trên Linux, tối đa giới hạn bởi số lượng bộ nhớ vật lý hiện tại, và tương đương với (xem kernel/fork.c:fork_init()): /* * Mặc định số lượng tối đa của chủ đề được thiết lập để một Két an toàn * giá trị: các cấu trúc chủ đề có thể mất tối đa một nửa * bộ nhớ. */ max_threads = mempages / (THREAD_SIZE/PAGE_SIZE) / 2;đó, trên kiến trúc IA32, về cơ bản có nghĩa là num_physpages/4. Ví dụ, trên máy 512M, bạn có thể tạo ra 32 k chủ đề. Đây là một cải tiến đáng kể vượt quá giới hạn 4k-epsilon cho lớn hạt nhân (2.2 và trước đó). Hơn nữa, điều này có thể thay đổi tại thời gian chạy bằng cách sử dụng KERN_MAX_THREADS sysctl(2), hoặc chỉ đơn giản bằng cách sử dụng các giao diện procfs để hạt nhân tunables: # Cát /proc/sys/kernel/threads-max 32764# echo 100000 > /proc/sys/kernel/threads-max # Cát /proc/sys/kernel/threads-max 100000# gdb - q vmlinux/proc/kcoreLõi đã được tạo ra bởi ' BOOT_IMAGE = 240ac18 ro gốc = 306 video = matrox:vesa:0x118'.#0 0x0 ở?? ()(gdb) p max_threads$1 = 100000Tập hợp các quá trình trên hệ thống Linux được thể hiện như một bộ sưu tập của các cấu trúc task_struct struct được liên kết theo hai cách:như là một hashtable, băm bởi pid, vàdöôùi daïng danh saùch tròn, gấp đôi liên kết bằng cách sử dụng p -> next_task và p -> prev_task con trỏ.Hashtable được gọi là pidhash [] và được định nghĩa trong include/linux/sched.h: / * PID băm. (điều này không nên động?) */#define PIDHASH_SZ (4096 >> 2)extern struct task_struct * pidhash [PIDHASH_SZ];#define pid_hashfn(x) (((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))Các tác vụ được băm bởi giá trị pid của họ và các chức năng trên hashing là nghĩa vụ phải phân phối các yếu tố thống nhất trong tên miền của họ (0-PID_MAX-1). Hashtable được sử dụng để nhanh chóng tìm thấy một công việc theo cấp pid, bằng cách sử dụng find_task_pid() nội tuyến từ include/linux/sched.h: nội tuyến tĩnh struct task_struct * find_task_by_pid(int pid){ struct task_struct * p ** htable = & pidhash[pid_hashfn(pid)]; cho (p = * htable; p & & p -> pid! = pid; p = p -> pidhash_next) ; trở về p;}Các nhiệm vụ trên mỗi hashlist (tức là băm để cùng một giá trị) được liên kết bởi p -> pidhash_next/pidhash_pprev được sử dụng bởi hash_pid() và unhash_pid() để chèn và loại bỏ một quá trình nhất định vào hashtable. Này được thực hiện dưới sự bảo hộ của spinlock đọc-ghi được gọi là tasklist_lock thực hiện để viết.Danh sách liên kết với gấp đôi tròn sử dụng p -> next_task/prev_task được duy trì vì vậy mà một trong những có thể đi qua tất cả nhiệm vụ trên hệ thống một cách dễ dàng. Điều này đạt được bởi vĩ mô for_each_task() từ include/linux/sched.h: #define for_each_task(p) được viết bởi admin cho (p = & init_task; (p = p -> next_task)! = & init_task; )Người sử dụng của for_each_task() nên dùng tasklist_lock cho đọc. Lưu ý rằng for_each_task() đang sử dụng init_task để đánh dấu đầu (và cuối) danh sách - đây là an toàn bởi vì nhiệm vụ nhàn rỗi (pid 0) không bao giờ ra khỏi.Công cụ điều chỉnh quá trình hashtable hoặc / và liên kết bảng cho quá trình, đặc biệt là fork(), exit() và ptrace(), phải mất tasklist_lock cho viết. Điều gì là thú vị hơn là những nhà văn cũng phải vô hiệu hóa ngắt trên CPU địa phương. Lý do cho việc này không phải là tầm thường: chức năng send_sigio() đi danh sách công việc và do đó mất tasklist_lock cho đọc, và nó được gọi là từ kill_fasync() trong bối cảnh gián đoạn. Đây là lý do tại sao nhà văn phải vô hiệu ngắt trong khi độc giả không phải.Bây giờ mà chúng tôi hiểu làm thế nào các cấu trúc task_struct được liên kết với nhau, chúng ta hãy xem xét các thành viên của task_struct. Họ lỏng lẻo tương ứng với các thành viên của UNIX 'struct proc' và 'struct người sử dụng' kết hợp với nhau.The other versions of UNIX separated the task state information into one part which should be kept memory-resident at all times (called 'proc structure' which includes process state, scheduling information etc.) and another part which is only needed when the process is running (called 'u area' which includes file descriptor table, disk quota information etc.). The only reason for such ugly design was that memory was a very scarce resource. Modern operating systems (well, only Linux at the moment but others, e.g. FreeBSD seem to improve in this direction towards Linux) do not need such separation and therefore maintain process state in a kernel memory-resident data structure at all times.The task_struct structure is declared in include/linux/sched.h and is currently 1680 bytes in size.The state field is declared as: volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */#define TASK_RUNNING 0#define TASK_INTERRUPTIBLE 1#define TASK_UNINTERRUPTIBLE 2#define TASK_ZOMBIE 4#define TASK_STOPPED 8#define TASK_EXCLUSIVE 32Why is TASK_EXCLUSIVE defined as 32 and not 16? Because 16 was used up by TASK_SWAPPING and I forgot to shift TASK_EXCLUSIVE up when I removed all references to TASK_SWAPPING (sometime in 2.3.x).The volatile in p->state declaration means it can be modified asynchronously (from interrupt handler):TASK_RUNNING: means the task is "supposed to be" on the run queue. The reason it may not yet be on the runqueue is that marking a task as TASK_RUNNING and placing it on the runqueue is not atomic. You need to hold the runqueue_lock read-write spinlock for read in order to look at the runqueue. If you do so, you will then see that every task on the runqueue is in TASK_RUNNING state. However, the converse is not true for the reason explained above. Similarly, drivers can mark themselves (or rather the process context they run in) as TASK_INTERRUPTIBLE (or TASK_UNINTERRUPTIBLE) and then call schedule(), which will then remove it from the runqueue (unless there is a pending signal, in which case it is left on the runqueue).TASK_INTERRUPTIBLE: means the task is sleeping but can be woken up by a signal or by expiry of a timer.TASK_UNINTERRUPTIBLE: same as TASK_INTERRUPTIBLE, except it cannot be woken up.TASK_ZOMBIE: task has terminated but has not had its status collected (wait()-ed for) by the parent (natural or by adoption).TASK_STOPPED: task was stopped, either due to job control signals or due to ptrace(2).TASK_EXCLUSIVE: this is not a separate state but can be OR-ed to either one of TASK_INTERRUPTIBLE or TASK_UNINTERRUPTIBLE. This means that when this task is sleeping on a wait queue with many other tasks, it will be woken up alone instead of causing "thundering herd" problem by waking up all the waiters.Task flags contain information about the process states which are not mutually exclusive: unsigned long flags; /* per process flags, defined below *//* * Per process flags */#define PF_ALIGNWARN 0x00000001 /* Print alignment warning msgs */ /* Not implemented yet, only for 486*/#define PF_STARTING 0x00000002 /* being created */#define PF_EXITING 0x00000004 /* getting shut down */#define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */#define PF_SUPERPRIV 0x00000100 /* used super-user privileges */#define PF_DUMPCORE 0x00000200 /* dumped core */#define PF_SIGNALED 0x00000400 /* killed by a signal */#define PF_MEMALLOC 0x00000800 /* Allocating memory */#define PF_VFORK 0x00001000 /* Wake up parent in mm_release */#define PF_USEDFPU 0x00100000 /* task used FPU this quantum (SMP) */The fields p->has_cpu, p->processor, p->counter, p->priority, p->policy and p->rt_priority are related to the scheduler and will be looked at later.The fields p->mm and p->active_mm point respectively to the process' address space described by mm_struct structure and to the active address space if the process doesn't have a real one (e.g. kernel threads). This helps minimise TLB flushes on switching address spaces when the task is scheduled out. So, if we are scheduling-in the kernel thread (which has no p->mm) then its next->active_mm will be set to the prev->active_mm of the task that was scheduled-out, which will be the same as prev->mm if prev->mm != NULL. The address space can be shared between threads if CLONE_VM flag is passed to the clone(2) system call or by means of vfork(2) system call.
The fields p->exec_domain and p->personality relate to the personality of the task, i.e. to the way certain system calls behave in order to emulate the "personality" of foreign flavours of UNIX.

The field p->fs contains filesystem information, which under Linux means three pieces of information:

root directory's dentry and mountpoint,
alternate root directory's dentry and mountpoint,
current working directory's dentry and mountpoint.
This structure also includes a reference count because it can be shared between cloned tasks when CLONE_FS flag is passed to the clone(2) system call.

The field p->files contains the file descriptor table. This too can be shared between tasks, provided CLONE_FILES is specified with clone(2) system call.

The field p->sig contains signal handlers and can be shared between cloned tasks by means of CLONE_SIGHAND.

2.2 Creation and termination of tasks and kernel threads

Different books on operating systems define a "process" in different ways, starting from "instance of a program in execution" and ending with "that which is produced by clone(2) or fork(2) system calls". Under Linux, there are three kinds of processes:

the idle thread(s),
kernel threads,
user tasks.
The idle thread is created at compile time for the first CPU; it is then "manually" created for each CPU by means of arch-specific fork_by_hand() in arch/i386/kernel/smpboot.c, which unrolls the fork(2) system call by hand (on some archs). Idle tasks share one init_task structure but have a private TSS structure, in the per-CPU array init_tss. Idle tasks all have pid = 0 and no other task can
đang được dịch, vui lòng đợi..
Kết quả (Việt) 2:[Sao chép]
Sao chép!
Tiếp theo Mục lục Trước
2. Quy trình quản lý và ngắt kết cấu 2.1 Nhiệm vụ và quá trình Bảng Mọi tiến trình trong Linux được cấp phát động một cấu trúc struct task_struct. Số lượng tối đa của các quá trình đó có thể được tạo ra trên Linux chỉ bị hạn chế bởi sự có mặt của bộ nhớ vật lý, và bằng (xem kernel / fork.c: fork_init ()): / * * Số lượng tối đa mặc định của đề tài được thiết lập đến một nơi an toàn * Giá trị: các cấu trúc sợi có thể mất nhiều nhất là nửa * bộ nhớ. * / max_threads = mempages / (THREAD_SIZE / PAGE_SIZE) / 2; trong đó, trên kiến trúc IA32, về cơ bản có nghĩa là num_physpages / 4. Như một ví dụ, trên một máy 512M, bạn có thể tạo chủ đề 32k. Đây là một cải tiến đáng kể so với giới hạn 4k-epsilon cho cũ (2.2 và trước đó) hạt nhân. Hơn nữa, điều này có thể được thay đổi trong thời gian chạy bằng cách sử dụng sysctl KERN_MAX_THREADS (2), hoặc chỉ đơn giản là sử dụng procfs giao diện hạt nhân tunables: # cat / proc / sys / kernel / đề-max 32.764 # echo 100000> / proc / sys / kernel / chủ đề -Max # cat / proc / sys / kernel / đề-max 100000 # gdb -q vmlinux / proc / kcore Core được tạo ra bởi `BOOT_IMAGE = 240ac18 gốc ro = 306 video = Matrox: 0x118 ': VESA. # 0 0x0 trong? ? () (Gdb) p max_threads $ 1 = 100000 Các thiết lập các quy trình trên hệ thống Linux được biểu diễn như là một tập hợp các cấu trúc task_struct struct được nối với nhau bằng hai cách: như một Hashtable, băm bởi pid, và như một vòng tròn, gấp đôi được liên kết danh sách sử dụng p-> next_task và p-> prev_task con trỏ. Các hashtable được gọi là pidhash [] và được định nghĩa trong include / linux / sched.h: / * PID băm. (? should này là năng động) * / #define PIDHASH_SZ (4096 >> 2) extern struct task_struct * pidhash [PIDHASH_SZ]; #define pid_hashfn (x) ((((x) >> 8) ^ (x)) & ( PIDHASH_SZ - 1)) Các nhiệm vụ được băm bằng giá trị pid của họ và các hàm băm trên là vụ để phân phối các yếu tố thống nhất trong phạm vi của họ (0 đến PID_MAX-1). Hashtable được sử dụng để nhanh chóng tìm thấy một công việc bởi pid nhất định, sử dụng find_task_pid () inline từ bao gồm / linux / sched.h: tĩnh inline struct task_struct * find_task_by_pid (int pid) {struct task_struct * p, ** htable = & pidhash [pid_hashfn (pid)]; for (p = * htable; p && p-> pid = pid;! p = p-> pidhash_next); trở lại p;} Các nhiệm vụ trên mỗi hashlist (tức là băm để cùng giá trị) được liên kết bởi p-> pidhash_next / pidhash_pprev được sử dụng bởi hash_pid () và unhash_pid () để chèn và loại bỏ một quá trình nhất định vào hashtable. Chúng được thực hiện dưới sự bảo vệ của các đọc-ghi spinlock gọi tasklist_lock đưa cho WRITE. Các danh sách gấp đôi được liên kết thông tư có sử dụng p-> next_task / prev_task được duy trì để người ta có thể đi qua tất cả các nhiệm vụ trên hệ thống một cách dễ dàng. Điều này đạt được bởi các for_each_task () vĩ mô từ bao gồm / linux / sched.h: #define for_each_task (p) cho (! P = & init_task; (p = p-> next_task) = & init_task;) Người sử dụng for_each_task () nên mất tasklist_lock cho READ. Lưu ý for_each_task rằng () được sử dụng init_task để đánh dấu sự khởi đầu (và kết thúc) của danh sách - đây là an toàn bởi vì nhiệm vụ nhàn rỗi (pid 0) không bao giờ thoát. Các bổ từ của quá trình hashtable hoặc / và các liên kết bảng tiến trình, đặc biệt là ngã ba (), exit () và ptrace (), phải mất tasklist_lock cho VIẾT. Điều thú vị hơn nữa là các nhà văn cũng phải vô hiệu hóa ngắt trên các CPU địa phương. Lý do cho điều này là không nhỏ: các send_sigio () chức năng đi danh sách công việc và do đó mất tasklist_lock cho READ, và nó được gọi từ kill_fasync () trong bối cảnh gián đoạn. Đây là lý do tại sao các nhà văn phải vô hiệu hóa ngắt trong khi độc giả không cần phải. Bây giờ chúng ta hiểu cách cấu trúc task_struct được liên kết với nhau, chúng ta hãy xem xét các thành viên của task_struct. Họ lỏng lẻo tương ứng với các thành viên của UNIX 'struct proc' và 'struct dùng kết hợp với nhau. Các phiên bản khác của UNIX tách các thông tin trạng thái nhiệm vụ thành một phần cần được lưu giữ bộ nhớ thường trú tại mọi thời điểm (gọi là "cấu trúc proc' mà bao gồm các trạng thái quá trình, lập kế hoạch thông tin, vv) và một phần khác mà chỉ cần thiết khi tiến trình đang chạy (gọi là "khu vực u 'bao gồm các tập tin bảng mô tả, thông tin hạn ngạch đĩa vv). Lý do duy nhất cho thiết kế xấu xí như là bộ nhớ là một nguồn lực rất khan hiếm. Hệ điều hành hiện đại (tốt, chỉ Linux vào lúc này nhưng những người khác, ví dụ như FreeBSD dường như để cải thiện theo hướng này hướng tới Linux) không cần cách ly như vậy và do đó duy trì quá trình nhà nước trong một bộ nhớ thường trú cấu trúc dữ liệu hạt nhân ở tất cả các lần. Cấu trúc task_struct được khai báo trong bao gồm / linux / sched.h và hiện tại là 1680 byte. Các lĩnh vực nhà nước được khai báo là: nhà nước dài biến động; / * -1 Unrunnable, 0 Runnable,> 0 ngừng * / #define TASK_RUNNING 0 #define TASK_INTERRUPTIBLE 1 #define TASK_UNINTERRUPTIBLE 2 #define TASK_ZOMBIE 4 #define TASK_STOPPED 8 #define TASK_EXCLUSIVE 32 Tại sao TASK_EXCLUSIVE định nghĩa là 32 và 16 không? . Bởi vì 16 được sử dụng hết bởi TASK_SWAPPING và tôi quên để chuyển TASK_EXCLUSIVE lên khi tôi loại bỏ tất cả các tài liệu tham khảo để TASK_SWAPPING (đôi khi trong 2.3.x) Những biến động trong p-> khai báo nhà nước có nghĩa là nó có thể được sửa đổi đồng bộ (từ xử lý ngắt): TASK_RUNNING : là công việc được "nghĩa là" trên hàng đợi chạy. Lý do nó có thể chưa được trên runqueue là đánh dấu một nhiệm vụ như TASK_RUNNING và đặt nó trên runqueue không phải là nguyên tử. Bạn cần phải giữ runqueue_lock đọc-ghi spinlock cho đọc để nhìn vào runqueue. Nếu bạn làm như vậy, sau đó bạn sẽ thấy rằng tất cả các nhiệm vụ trên runqueue ở trạng thái TASK_RUNNING. Tuy nhiên, chuyện này là không đúng đối với những lý do giải thích ở trên. Tương tự như vậy, trình điều khiển có thể đánh dấu bản thân (hay đúng hơn là bối cảnh quá trình họ chạy trong) như TASK_INTERRUPTIBLE (hoặc TASK_UNINTERRUPTIBLE) và sau đó gọi lịch (), sau đó sẽ loại bỏ nó từ runqueue (trừ khi có một tín hiệu cấp phát, trong trường hợp này nó là còn lại trên runqueue). TASK_INTERRUPTIBLE: có nghĩa là nhiệm vụ đang ngủ nhưng có thể được đánh thức bởi một tín hiệu hoặc hết hạn của một bộ đếm thời gian. TASK_UNINTERRUPTIBLE: giống như TASK_INTERRUPTIBLE, ngoại trừ nó không thể được đánh thức. TASK_ZOMBIE: nhiệm vụ đã chấm dứt nhưng đã không có thu thập tình trạng của nó (wait () - ed cho) của phụ huynh (tự nhiên hoặc do con nuôi). TASK_STOPPED:. nhiệm vụ đã được ngừng lại, hoặc là do các tín hiệu điều khiển công việc hoặc do ptrace (2) TASK_EXCLUSIVE: đây không phải là một nhà nước riêng biệt nhưng có thể là OR-ed để một trong hai TASK_INTERRUPTIBLE hoặc TASK_UNINTERRUPTIBLE. Điều này có nghĩa là khi nhiệm vụ này đang ngủ trên một hàng đợi để chờ đợi với nhiều nhiệm vụ khác, nó sẽ được đánh thức một mình thay vì gây "sấm bầy đàn" vấn đề bằng cách thức dậy tất cả những người phục vụ. Cờ công tác có chứa thông tin về các trạng thái quá trình mà không tương quan độc quyền: cờ unsigned dài; / * Mỗi cờ quy trình, quy định dưới đây * / / * * mỗi quá trình cờ * / bản tin #define PF_ALIGNWARN 0x00000001 / * In cảnh báo alignment * / / * Chưa triển khai, chỉ cho 486 * / #define PF_STARTING 0x00000002 / * được tạo ra * / # define PF_EXITING 0x00000004 / * lấy tắt * / #define PF_FORKNOEXEC 0x00000040 / * chia hai nhưng không exec * / #define PF_SUPERPRIV 0x00000100 / * sử dụng đặc quyền của siêu người dùng * / #define PF_DUMPCORE 0x00000200 / * đổ lõi * / # định nghĩa các PF_SIGNALED 0x00000400 / * giết bởi một tín hiệu * / PF_MEMALLOC #define 0x00000800 / * Cấp phát bộ nhớ * / #define PF_VFORK 0x00001000 / * Wake up phụ huynh trong mm_release * / #define PF_USEDFPU 0x00100000 / * nhiệm vụ sử dụng FPU lượng tử này (SMP) * / Các lĩnh vực p-> has_cpu, p-> xử lý, p-> truy cập, p-> ưu tiên, p-> chính sách và p-> rt_priority có liên quan đến lịch trình và sẽ được xem xét sau. Các trường p-> mm và p-> active_mm điểm tương ứng với quá trình không gian địa chỉ "được miêu tả bởi cấu trúc mm_struct và không gian địa chỉ hoạt động nếu quá trình không có một thực tế (ví dụ như kernel chủ đề). Điều này giúp giảm thiểu TLB bừng trên chuyển mạch không gian địa chỉ khi công việc được lên kế hoạch ra. Vì vậy, nếu chúng ta đang lên kế hoạch trong các chủ đề hạt nhân (mà không có p-> mm) sau đó nó next-> active_mm sẽ được thiết lập để các prev-> active_mm của nhiệm vụ đã được lên lịch ra, mà sẽ được giống như prev-> mm nếu prev-> mm! = NULL. Không gian địa chỉ có thể được chia sẻ giữa các chủ đề nếu CLONE_VM cờ được thông qua để clone (2) gọi hệ thống hoặc bằng phương tiện của vfork (2) gọi hệ thống. Các lĩnh vực p-> exec_domain và p-> cá tính liên quan đến tính cách của nhiệm vụ , tức là cách các cuộc gọi hệ thống nhất định ứng xử để tranh đua với "cá tính" của hương vị nước ngoài của UNIX. Các lĩnh vực p-> fs chứa thông tin hệ thống tập tin, mà dưới Linux có nghĩa là ba mẩu thông tin: dentry thư mục gốc của điểm láp, rễ thay thế dentry thư mục của điểm láp, dentry thư mục làm việc hiện tại của điểm láp. Cấu trúc này cũng bao gồm một số tài liệu tham khảo, vì nó có thể được chia sẻ giữa các công việc nhân bản vô tính khi CLONE_FS cờ được thông qua để clone (2) gọi hệ thống. Các lĩnh vực p-> file này đều chứa các tập tin bảng mô tả. Điều này cũng có thể được chia sẻ giữa các tác vụ, cung cấp CLONE_FILES được quy định với clone (2) gọi hệ thống. Các lĩnh vực p-> sig chứa xử lý tín hiệu và có thể được chia sẻ giữa các công việc nhân bản vô tính bằng phương tiện của CLONE_SIGHAND. 2.2 Tạo và chấm dứt nhiệm vụ và đề hạt nhân sách khác nhau trên hệ điều hành xác định một "quá trình" theo những cách khác nhau, bắt đầu từ "thể hiện của một chương trình trong thực hiện" và kết thúc bằng "rằng đó là sản phẩm của clone (2) hoặc cuộc gọi fork (2) Hệ thống". Trong Linux, có ba loại quy trình: thread nhàn rỗi (s), đề hạt nhân, nhiệm vụ người dùng. Các thread nhàn rỗi được tạo ra tại thời gian biên dịch cho các CPU đầu tiên; đó là sau đó "bằng tay" tạo ra cho mỗi CPU bằng vòm cụ thể fork_by_hand () trong arch / i386 / kernel / smpboot.c, mà unrolls ngã ba (2) hệ thống gọi bằng tay (trên một số archs). Nhiệm vụ nhàn rỗi chia sẻ một cấu trúc init_task nhưng có một cấu trúc TSS tin, trong mảng init_tss mỗi CPU. Nhiệm vụ nhàn rỗi tất cả đã PID = 0 và không có nhiệm vụ khác có thể


























































































































đang được dịch, vui lòng đợi..
 
Các ngôn ngữ khác
Hỗ trợ công cụ dịch thuật: Albania, Amharic, Anh, Armenia, Azerbaijan, Ba Lan, Ba Tư, Bantu, Basque, Belarus, Bengal, Bosnia, Bulgaria, Bồ Đào Nha, Catalan, Cebuano, Chichewa, Corsi, Creole (Haiti), Croatia, Do Thái, Estonia, Filipino, Frisia, Gael Scotland, Galicia, George, Gujarat, Hausa, Hawaii, Hindi, Hmong, Hungary, Hy Lạp, Hà Lan, Hà Lan (Nam Phi), Hàn, Iceland, Igbo, Ireland, Java, Kannada, Kazakh, Khmer, Kinyarwanda, Klingon, Kurd, Kyrgyz, Latinh, Latvia, Litva, Luxembourg, Lào, Macedonia, Malagasy, Malayalam, Malta, Maori, Marathi, Myanmar, Mã Lai, Mông Cổ, Na Uy, Nepal, Nga, Nhật, Odia (Oriya), Pashto, Pháp, Phát hiện ngôn ngữ, Phần Lan, Punjab, Quốc tế ngữ, Rumani, Samoa, Serbia, Sesotho, Shona, Sindhi, Sinhala, Slovak, Slovenia, Somali, Sunda, Swahili, Séc, Tajik, Tamil, Tatar, Telugu, Thái, Thổ Nhĩ Kỳ, Thụy Điển, Tiếng Indonesia, Tiếng Ý, Trung, Trung (Phồn thể), Turkmen, Tây Ban Nha, Ukraina, Urdu, Uyghur, Uzbek, Việt, Xứ Wales, Yiddish, Yoruba, Zulu, Đan Mạch, Đức, Ả Rập, dịch ngôn ngữ.

Copyright ©2024 I Love Translation. All reserved.

E-mail: