Chinaunix首页 | 论坛 | 博客
  • 博客访问: 55736
  • 博文数量: 47
  • 博客积分: 2095
  • 博客等级: 大尉
  • 技术积分: 560
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-01 18:42
文章分类

全部博文(47)

文章存档

2011年(1)

2008年(46)

我的朋友

分类: LINUX

2008-04-26 14:32:18

Creating Processes

Unix operating systems rely heavily on process creation to satisfy user requests. For example, the shell creates a new process that executes another copy of the shell whenever the user enters a command.

Traditional Unix systems treat all processes in the same way: resources owned by the parent process are duplicated in the child process. This approach makes process creation very slow and inefficient, because it requires copying the entire address space of the parent process. The child process rarely needs to read or modify all the resources inherited from the parent; in many cases, it issues an immediate execve( ) and wipes out the address space that was so carefully copied.

传统的Unix系统这样对待所有的进程:父进程拥有的资源会复制一份给子进程。这种方法使得进程创建很慢并效率很低,因为需要复制父进程的整个地址空间。子进程很少需要读或者修改所有从父进程继承过来的资源;在很多情形下,它立刻使用execve()并换出小心翼翼复制的地址空间。

Modern Unix kernels solve this problem by introducing three different mechanisms:

· The Copy On Write technique allows both the parent and the child to read the same physical pages. Whenever either one tries to write on a physical page, the kernel copies its contents into a new physical page that is assigned to the writing process. The implementation of this technique in Linux is fully explained in Chapter 9.

写时拷贝技术允许父进程和子进程读同一个物理页面。无论何时其中之一试图写这个物理页面,内核拷贝它的内容到一个新的物理页面,并将新的页面分配给执行写操作的进程。

· Lightweight processes allow both the parent and the child to share many per-process kernel data structures, such as the paging tables (and therefore the entire User Mode address space), the open file tables, and the signal dispositions.
轻进程允许父进程和子进程共享多个每进程的内核数据结构,比如页表(因此整个用户空间),打开的文件表,和信号部署。

· The vfork( ) system call creates a process that shares the memory address space of its parent. To prevent the parent from overwriting data needed by the child, the parent's execution is blocked until the child exits or executes a new program. We'll learn more about the vfork( ) system call in the following section.
系统调用vfork()创建了一个进程,共享它父进程的内存地址空间。为了阻止父进程改写子进程需要的数据,父进程的执行阻塞直到子进程退出或执行一个新的程序。

The clone( ), fork( ), and vfork( ) System Calls

Lightweight processes are created in Linux by using a function named clone( ), which uses the following parameters:

在Linux中轻进程是通过使用函数clone()创建,它使用下列参数:

fn

Specifies a function to be executed by the new process; when the function returns, the child terminates. The function returns an integer, which represents the exit code for the child process.

指明新进程执行的函数;当这个函数返回时,子进程终止。这个函数返回一个整数,代表子进程的退出码。

arg

Points to data passed to the fn( ) function.

执行传给fn()函数的数据。

flags

Miscellaneous information. The low byte specifies the signal number to be sent to the parent process when the child terminates; the SIGCHLD signal is generally selected. The remaining three bytes encode a group of clone flags, which are shown in Table 3-8.

各种信息。低byte指明当子进程终止时,需要送给父进程的信号值;通常会选择SIGCHID信号。剩下3byte是一种clone标志的编码。

child_stack

Specifies the User Mode stack pointer to be assigned to the esp register of the child process. The invoking process (the parent) should always allocate a new stack for the child.

指明将要分配给子进程的esp寄存器的用户空间栈指针。调用进程(父进程)应该总是为子进程分配一个新的栈。

tls

Specifies the address of a data structure that defines a Thread Local Storage segment for the new lightweight process (see the section "The Linux GDT" in Chapter 2). Meaningful only if the CLONE_SETTLS flag is set.

指明为新的轻进程定义的TLS段结构的地址。仅在CLONE_SETTLS标志设置的情况下有意义。

ptid

Specifies the address of a User Mode variable of the parent process that will hold the PID of the new lightweight process. Meaningful only if the CLONE_PARENT_SETTID flag is set.

指明父进程中保存新的轻进程PID的用户空间变量的地址。仅在CLONE_PARENT_SETTID设置时有效。

ctid

Specifies the address of a User Mode variable of the new lightweight process that will hold the PID of such process. Meaningful only if the CLONE_CHILD_SETTID flag is set.

指明新的轻进程中保存进程PID的用户空间变量的地址。仅在CLONE_PARENT_SETTID设置时有效。

Table 3-8. Clone flags
 
 Flag name   Description
 CLONE_VM  Shares the memory descriptor and all Page Tables (see Chapter 9).
共享内存描述符和所有的页表。 
 CLONE_FS  Shares the table that identifies the root directory and the current working directory, as well as the value of the bitmask used to mask the initial file permissions of a new file (the so-called file umask ).
共享标识根目录和当前工作目录的表,和初始化新文件的文件权限的bitmask(也叫文件umask) 
 CLONE_FILES  Shares the table that identifies the open files (see Chapter 12).共享标识打开文件的表。
 CLONE_SIGHAND  Shares the tables that identify the signal handlers and the blocked and pending signals (see Chapter 11). If this flag is true, the CLONE_VM flag must also be set.
共享标识信号处理函数和阻塞和未处理信号的表。如果这个标志为真,那么CLONE_VM也必须设置。
 CLONE_PTRACE  If traced, the parent wants the child to be traced too. Furthermore, the debugger may want to trace the child on its own; in this case, the kernel forces the flag to 1.
如果被跟踪,父进程想让子进程也被跟踪。调试器可能希望单独跟踪子进程,这种情况下,内核强迫设置该标志为1.
 CLONE_VFORK  Set when the system call issued is a vfork( ) (see later in this section).
当系统调用是由vfork()提出时设置。
 CLONE_PARENT  Sets the parent of the child (parent and real_parent fields in the process descriptor) to the parent of the calling process.
设置子进程的父进程(进程描述符的parent和real_parent成员)为调用进程的父进程。
 CLONE_THREAD  Inserts the child into the same thread group of the parent, and forces the child to share the signal descriptor of the parent. The child's tgid and group_leader fields are set accordingly. If this flag is true, the CLONE_SIGHAND flag must also be set.
将子进程插入父进程的同一个线程组,并强制子进程共享父进程的信号描述符。子进程的tgid和group_leader成员做相应的设置。如果这个标志为真,那么CLONE_SIGHAND标志必须设置。
 CLONE_NEWNS  Set if the clone needs its own namespace, that is, its own view of the mounted filesystems (see Chapter 12); it is not possible to specify both CLONE_NEWNS and CLONE_FS.
如果clone需要自己的命名空间时设置,即自己的安装文件系统的视图;不可能同时设置CLONE_NEWNS和CLONE_FS。
 CLONE_SYSVSEM  Shares the System V IPC undoable semaphore operations (see the section "IPC Semaphores" in Chapter 19).
共享systemV IPC 信号量操作。
 CLONE_SETTLS  Creates a new Thread Local Storage (TLS) segment for the lightweight process; the segment is described in the structure pointed to by the tls parameter.
为轻进程创建一个新的TLS段;这个段由tls参数指向的结构描述。
 CLONE_PARENT_SETTID  Writes the PID of the child into the User Mode variable of the parent pointed to by the ptid parameter.将子进程的PID写入由ptid参数指向的父进程用户空间变量。
 CLONE_CHILD_CLEARTID 

When set, the kernel sets up a mechanism to be triggered when the child process will exit or when it will start executing a new program. In these cases, the kernel will clear the User Mode variable pointed to by the ctid parameter and will awaken any process waiting for this event.
当设置时,内核设立一个机制,当子进程退出或当它开始执行一个新的程序时触发。在这种情况下,内核将清除有ctid参数指向的用户空间变量并唤醒等待这个事件的每个进程。

 CLONE_DETACHED  A legacy flag ignored by the kernel.
忽略
 CLONE_UNTRACED  Set by the kernel to override the value of the CLONE_PTRACE flag (used for disabling tracing of kernel threads ; see the section "Kernel Threads" later in this chapter).
由内核设置,覆盖CLONE_PTRACE标志
 CLONE_CHILD_SETTID  Writes the PID of the child into the User Mode variable of the child pointed to by the ctid parameter.
将子进程的PID写入由ctid参数指向的子进程的用户空间变量。
 CLONE_STOPPED Forces the child to start in the TASK_STOPPED state.
强迫子进程从TASK_STOPPED状态开始

clone( ) is actually a wrapper function defined in the C library (see the section "POSIX APIs and System Calls" in Chapter 10), which sets up the stack of the new lightweight process and invokes a clone( ) system call hidden to the programmer. The sys_clone( ) service routine that implements the clone( ) system call does not have the fn and arg parameters. In fact, the wrapper function saves the pointer fn into the child's stack position corresponding to the return address of the wrapper function itself; the pointer arg is saved on the child's stack right below fn. When the wrapper function terminates, the CPU fetches the return address from the stack and executes the fn(arg) function.

clone()实际是C库中定义的包装函数,它建立了新的轻进程的栈并调用对程序员隐藏的系统调用clone()。实现clone()系统调用的服务程序sys_clone()没有fn和arg参数。事实上,包装函数将fn指针保存在子进程的栈中对应包装器本身的返回地址的位置;指针arg保存在子进程的栈中fn下面。当包装函数结束时,CPU从栈中取得返回地址并开始执行fn(arg)函数。

The traditional fork( ) system call is implemented by Linux as a clone( ) system call whose flags parameter specifies both a SIGCHLD signal and all the clone flags cleared, and whose child_stack parameter is the current parent stack pointer. Therefore, the parent and child temporarily share the same User Mode stack. But thanks to the Copy On Write mechanism, they usually get separate copies of the User Mode stack as soon as one tries to change the stack.

传统的fork()系统调用在Linux是通过一个clone()系统调用实现的,对应的flags参数指明了一个SIGCHLD信号和所有的clone标志清空,child_stack参数是当前父进程的栈指针。因此,父进程和子进程临时地共享同一用户空间栈。但由于写时拷贝机制,一旦其中之一试图改变栈时,它们通常会得到用户空间栈的一份独立的拷贝。

The vfork( ) system call, introduced in the previous section, is implemented by Linux as a clone( ) system call whose flags parameter specifies both a SIGCHLD signal and the flags CLONE_VM and CLONE_VFORK, and whose child_stack parameter is equal to the current parent stack pointer.

vfork()系统调用,Linux通过一个clone()系统调用实现,对应的flags参数指明了SIGCHLD信号和CLONE_VM和CLONE_VFORK标志,child_stack参数等于当前父进程的栈指针。
阅读(282) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~