注意到,当前的任务是?insmod
,这是因为?init_module
?函数是在?insmod
?命令执行的上下文运行的。current
?符号实际指的是一个函数(get_current
)并可在一个与 arch 有关的头部中找到(比如 ./linux/include/asm-i386/current.h 内找到)。
您可能已经看到过系统调用的模式了。在很多情况下,系统调用都被命名为?sys_*
?并提供某些初始功能以实现调用(例如错误检查或用户空间的行为)。实际的工作常常会委派给另外一个名为?do_*
?的函数。
让我们不妨亲自看看如何从用户空间创建一个进程。用户空间任务和内核任务的底层机制是一致的,因为二者最终都会依赖于一个名为?do_fork
?的函数来创建新进程。在创建内核线程时,内核会调用一个名为?kernel_thread
?的函数(参见 ./linux/arch/i386/kernel/process.c),此函数执行某些初始化后会调用?do_fork
。
创建用户空间进程的情况与此类似。在用户空间,一个程序会调用?fork
,这会导致对名为sys_fork
?的内核函数的系统调用(参见 ./linux/arch/i386/kernel/process.c)。函数关系如图 1 所示。

从图 1 中,可以看到?do_fork
?是进程创建的基础。可以在 ./linux/kernel/fork.c 内找到?do_fork
?函数(以及合作函数?copy_process
)。
do_fork
?函数首先调用?alloc_pidmap
,该调用会分配一个新的 PID。接下来,do_fork
?检查调试器是否在跟踪父进程。如果是,在clone_flags
?内设置?CLONE_PTRACE
?标志以做好执行 fork 操作的准备。之后?do_fork
?函数还会调用?copy_process
,向其传递这些标志、堆栈、注册表、父进程以及最新分配的 PID。
新的进程在?copy_process
?函数内作为父进程的一个副本创建。此函数能执行除启动进程之外的所有操作,启动进程在之后进行处理。copy_process
?内的第一步是验证?CLONE
?标志以确保这些标志是一致的。如果不一致,就会返回?EINVAL
?错误。接下来,询问 Linux Security Module (LSM) 看当前任务是否可以创建一个新任务。要了解有关 LSM 在 Security-Enhanced Linux (SELinux) 上下文中的更多信息,请参见??小节。
接下来,调用?dup_task_struct
?函数(在 ./linux/kernel/fork.c 内),这会分配一个新?task_struct
?并将当前进程的描述符复制到其内。在新的线程堆栈设置好后,一些状态信息也会被初始化,并且会将控制返回给?copy_process
。控制回到?copy_process
?后,除了其他几个限制和安全检查之外,还会执行一些常规管理,包括在新?task_struct
?上的各种初始化。之后,会调用一系列复制函数来复制此进程的各个方面,比如复制开放文件描述符(copy_files
)、复制符号信息(copy_sighand
?和?copy_signal
)、复制进程内存(copy_mm
)以及最终复制线程(copy_thread
)。
之后,这个新任务会被指定给一个处理程序,同时对允许执行进程的处理程序进行额外的检查(cpus_allowed
)。新进程的优先级从父进程的优先级继承后,执行一小部分额外的常规管理,而且控制也会被返回给?do_fork
。在此时,新进程存在但尚未运行。do_fork
?函数通过调用wake_up_new_task
?来修复此问题。此函数(可在 ./linux/kernel/sched.c 内找到)初始化某些调度程序的常规管理信息,将新进程放置在运行队列之内,然后将其唤醒以便执行。最后,一旦返回至?do_fork
,此 PID 值即被返回给调用程序,进程完成。
(编辑:应用网_丽江站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!