加入收藏 | 设为首页 | 会员中心 | 我要投稿 东莞站长网 (https://www.0769zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux 进程管理剖析--转

发布时间:2021-01-24 05:12:40 所属栏目:Linux 来源:网络整理
导读:地址:http://www.ibm.com/developerworks/cn/linux/l-linux-process-management/index.html Linux 是一种动态系统,能够适应不断变化的计算需求。Linux 计算需求的表现是以 进程 ?的通用抽象为中心的。进程可以是短期的(从命令行执行的一个命令),也可以

/ Walk through the task list,until we hit the init_task again /
do {

printk( KERN_INFO "*** %s [%d] parent %sn",<strong>task->comm</strong>,<strong>task->pid</strong>,<strong>task->parent->comm</strong> );

} while ( (task = next_task(task)) != &init_task );

return 0;

}

void cleanup_module( void )
{
return;
}

可以用清单 3 所示的 Makefile 编译此模块。在编译时,可以用?insmod procsview.ko?插入模块对象,也可以用?rmmod procsview?删除它。

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

插入后,/var/log/messages 可显示输出,如下所示。从中可以看到,这里有一个空闲任务(称为?swapper)和?init?任务(pid 1)。

注意,还可以标识当前正在运行的任务。Linux 维护一个称为?current?的符号,代表的是当前运行的进程(类型是?task_struct)。如果在init_module?的尾部插入如下这行代码:

comm,current->pid );

会看到:

注意到,当前的任务是?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 值即被返回给调用程序,进程完成。

(编辑:东莞站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读