当前位置:首页 > 嵌入式 > 嵌入式软件

作者:李智敏,华清远见嵌入式学院上海分中心讲师。

在 Linux 内核内,进程是由相当大的一个称为 task_STruct 的结构表示的。此结构包含所有表示此进程所必需的数据,此外,还包含了大量的其他数据用来统计(accounTIng)和维护与其他进程的关系(父和子)。下面给出了 task_struct 的一小部分。task_struct 位于 ./linux/include/linux/sched.h。

struct task_struct {

volatile lONg state;

void *stack;

unsigned int flags;

int prio, static_prio;

struct list_head tasks;

struct mm_struct *mm, *active_mm;

pid_t pid;

pid_t tgid;

struct task_struct *real_parent;

char comm[TASK_COMM_LEN];

struct thread_struct thread;

struct files_struct *files;

...

};

在task_struct中,可以看到几个预料之中的项,比如执行的状态、堆栈、一组标志、父进程、执行的线程(可以有很多)以及开放文件。对其做简单声明如下

<1> state 变量是一些表明任务状态的比特位。最常见的状态有:

1.TASK_RUNNING 表示进程正在运行,或是排在运行队列中正要运行

2.TASK_INTERRUPTIBLE 表示进程正在休眠

3.TASK_UNINTERRUPTIBLE 表示进程正在休眠但不能叫醒

4.TASK_STOPPED 表示进程停止

注:这些标志的完整列表可以在 ./linux/include/linux/sched.h 内找到。

<2> flags 定义了很多指示符,表明进程是否正在被创建(PF_STARTING)或退出(PF_EXITING),或是进程当前是否在分配内存(PF_MEMALLOC)。

<3> 每个进程都会被赋予优先级(称为 static_prio),但进程的实际优先级是基于加载以及其他几个因素动态决定的。优先级值越低,实际的优先级越高。

<4> tasks 字段提供了链接列表的能力。它包含一个 prev 指针(指向前一个任务)和一个 next 指针(指向下一个任务)。

<5> 进程的地址空间由 mm 和 active_mm 字段表示。mm 代表的是进程的内存描述符,而 active_mm 则是前一个进程的内存描述符(为改进上下文切换时间的一种优化)。

<6> 可执行程序的名称(不包含路径)占用 comm(命令)字段。

<7> thread_struct 则用来标识进程的存储状态。此元素依赖于 Linux 在其上运行的特定架构,在 ./linux/include/asm-i386/processor.h 内有这样的一个例子。在此结构内,可以找到该进程自执行上下文切换后的存储(硬件注册表、程序计数器等)。

在很多情况下,进程都是动态创建并由一个动态分配的 task_struct 表示。当然 init 进程例外,它总是存在并由一个静态分配的 task_struct 表示。

Linux 内所有进程的分配有两种方式。第一种方式是通过一个哈希表,由 PID 值进行哈希计算得到;第二种方式是通过双链循环表。循环表非常适合于对任务列表进行迭代。由于列表是循环的,没有头或尾;但是由于 init_task 总是存在,所以可以将其用作继续向前迭代的一个锚点。

任务列表无法从用户空间访问,但该问题很容易解决,方法是以模块形式向内核内插入代码。例如通过如下代码,它会迭代任务列表并会提供有关每个任务的少量信息(name、pid 和 parent 名)。

struct task_struct *task = &init_task;

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

do {

printk( KERN_INFO "*** %s [%d] parent %s\n",

task->comm, task->pid, task->parent->comm );

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

注意,还可以标识当前正在运行的任务。Linux 维护一个称为 current 的符号,代表的是当前运行的进程(类型是 task_struct)。为此可使用如下代码:

printk( KERN_INFO, "Current task is %s [%d]”, current->comm, current->pid );

Linux创建用户空间进程的情况与内核空间进程类似。二者底层机制是一致的,因为最终都会依赖于一个名为 do_fork 的函数来创建新进程。

在创建内核线程时,内核会调用一个名为 kernel_thread 的函数(参见 ./linux/arch/i386/kernel/process.c),此函数执行某些初始化后会调用 do_fork。

在用户空间,一个程序会调用 fork,这会导致对名为 sys_fork 的内核函数的系统调用(参见 ./linux/arch/i386/kernel/process.c)。

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) 看当前任务是否可以创建一个新任务。

接下来,调用 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 值即被返回给调用程序,进程完成。

“本文由华清远见http://www.embedu.org/index.htm提供”



华清远见

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

为了满足日益增长的数据处理需求,铁威马NAS推出了全新的性能巅峰2024年旗舰之作F4-424 Pro,并搭载了最新的操作系统--TOS 6。这款高效办公神器的问世,无疑将为企业和专业人士带来前所未有的便捷与效率。

关键字: 存储 Linux 服务器

双系统将是下述内容的主要介绍对象,通过这篇文章,小编希望大家可以对双系统的相关情况以及信息有所认识和了解,详细内容如下。

关键字: 双系统 Windows Linux

安装Linux操作系统并不复杂,下面是一个大致的步骤指南,以帮助您完成安装。1. 下载Linux发行版:首先,您需要从Linux发行版官方网站下载最新的ISO镜像文件。

关键字: Linux 操作系统 ISO镜像

计算机是由一堆硬件组成的,为了有限的控制这些硬件资源,于是就有了操作系统的产生,操作系统是软件子系统的一部分,是硬件基础上的第一层软件。

关键字: Linux 操作系统 计算机

Linux操作系统是一套免费使用和自由传播的类Unix操作系统,通常被称为GNU/Linux。它是由林纳斯·托瓦兹在1991年首次发布的,并基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。Lin...

关键字: Linux 操作系统

所谓进程间通信就是在不同进程之间传播或交换信息,它是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息;还可以让一个程序能够在同一时间里处理许多用户的需求。

关键字: Linux 进程通信 编程接口

串口通信作为一种最传统的通信方式,在工业自动化、通讯、控制等领域得到广泛使用。

关键字: Linux 串口通信 通讯

2023年11月16日: MikroElektronika(MIKROE) ,作为一家通过提供基于成熟标准的创新式硬软件产品来大幅缩短开发时间的嵌入式解决方案公司,今天宣布推出一款基于单线设备的软硬件开源解决方案Cli...

关键字: 嵌入式 Linux 操作系统

Linux是一种免费使用和自由传播的类Unix操作系统,其内核由林纳斯·本纳第克特·托瓦兹于1991年10月5日首次发布。它主要受到Minix和Unix思想的启发,是一个基于POSIX的多用户、多任务、支持多线程和多CP...

关键字: Linux 操作系统

本文中,小编将对嵌入式予以介绍,如果你想对它的详细情况有所认识,或者想要增进对它的了解程度,不妨请看以下内容哦。

关键字: 嵌入式 Linux
关闭
关闭