6.3.2 Xenomai/Linux进程/主线程描述符之间的关联

点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

6.3.2 Xenomai/Linux进程/主线程描述符之间的关联

本文分析进程/主线程创建的过程及相互的关联。
在这里插入图片描述

1. Linux进程描述符struct task_struct的创建

参考《6.1.4 Xenomai3: hello world如何变成Xenomai实时进程》的分析,在Linux Shell下启动应用程序,会经历如下标准流程:

(1)Fork 函数:Shell 使用 fork() 函数,调用sys_fork系统调用来创建一个新的子线程并分配struct task_struct。此时,子进程是父进程(通常是 Shell)的一个副本,包括内存空间、文件描述符等。注意,此时struct task_struct仅仅是Shell的子线程。

(2)Exec 系列函数:在子线程中,Shell 调用 execve() 或其他 exec 系列函数之一来加载并执行指定的 ELF 文件。这一步会替换当前进程的用户空间镜像为新程序的镜像。此时,子线程将拥有自己的虚拟地址空间,可用称为一个独立的进程,它的父进程为Shell。

至此,Linux进程描述符struct task_stuct已经创建完毕。

2. Xenomai进程描述符struct cobalt_process的创建

libc_start_main 是 glibc 内部函数,负责进一步初始化运行时环境,包括调用__libc_csu_init初始化全局构造函数和静态构造函数,即执行所有带有__attribute((constructor))属性的函数以及C++中的静态对象构造函数。

Xenomai3 利用GCC的 attribute((constructor)) 特性来定义了3种优先级的构造函数。凡是有这3个宏作为前缀的函数,总是会在__libc_csu_init中被执行。
在这里插入图片描述
在__setup_ctor中,关注struct setup_descriptor cobalt_interface,它的init函数是cobalt_init。

在这里插入图片描述
cobalt_init会调用sc_coablt_bind系统调用创建struct cobalt_process。

cobalt_init
->cobalt_init_1()
->cobalt_init_2()
	->low_init() // 调用sc_coablt_bind系统调用创建cobalt_process

陷入内核,执行系统调用sc_coablt_bind,调用堆栈如下。

static COBALT_SYSCALL(bind, lostage,
              (struct cobalt_bindreq __user *u_breq)) //系统调用
->cobalt_bind_core
->bind_personality(&cobalt_personality)
->personality->ops.attach_process
->cobalt_process_attach // 申请struct cobalt_process结构体
->cobalt_set_process(process); //->struct ipipe_threadinfo ipipe_data.process指向新申请的struct cobalt_process结构体

(1)cobalt_process_attach
在这里插入图片描述
第1028行,申请struct cobalt_process结构体。
第1032行,调用attach_process把cobalt_process加入process_hash哈希链表。

(2)cobalt_set_process

在这里插入图片描述

最终在cobalt_set_process中,struct ipipe_threadinfo ipipe_data.process指向新申请的struct cobalt_process结构体。

至此,Linux进程描述符struct task_struct通过struct ipipe_threadinfo中的process指针,指向了Xenomai进程描述符struct cobalt_process结构体。

3. Xenomai主线程描述符struct cobalt_thread的创建

回到上文提到的cobalt_init,它不仅会调用sc_coablt_bind系统调用创建cobalt_process,而且会继续创建Xenomai主线程描述符struct cobalt_thread。

cobalt_init
->cobalt_init_1()
->cobalt_init_2()
	->low_init() // 调用sc_coablt_bind系统调用创建cobalt_process
-> __RT(pthread_setschedparam(ptid, policy, &parm)) 
	->pthread_setschedparam_ex // 系统调用sc_cobalt_thread_setschedparam_ex创建struct cobalt_thread。

pthread_setschedparam_ex调用系统调用sc_cobalt_thread_setschedparam_ex创建struct cobalt_thread。
在这里插入图片描述

系统调用sc_cobalt_thread_setschedparam_ex在Xenomai内核中的实现如下。

COBALT_SYSCALL(thread_setschedparam_ex, conforming,
           (unsigned long pth,
        int policy,
        const struct sched_param_ex __user *u_param,
        __u32 __user *u_winoff,
        int __user *u_promoted))
-> cobalt_thread_setschedparam_ex
-> thread_lookup_or_shadow
-> cobalt_thread_shadow
-> pthread_create //创建struct cobalt_thread,插入struct cobalt_process中thread_list链表!
-> cobalt_map_user //将struct cobalt_thread变成Linux struct task_struct的影子

(1)thread_lookup_or_shadow
在这里插入图片描述
第469行,调用thread_lookup,通过hkey在哈希链表来查找是否有匹配的struct cobalt_thread。
hkey.u_pth是从用户层传下来的pthread_t thread。pthread_t thread是 用户层POSIX 线程库中的一个数据类型,用来表示线程的标识符。在用户层这个标识符可以用来在程序中唯一地标识当前线程,而IPIPE借用了这个标识符。
hkey.mm是复用Linux中struct task_struct中的struct mm_struct指针,对于一个进程来说,主线程和所有子线程是共享虚拟地址空间的,所以struct mm_struct指针是唯一的。

第474行,因为当前处于新的进程创建过程,所以肯定是无法查找出匹配的struct cobalt_thread,会走到cobalt_thread_shadow创建新的struct cobalt_thread。

(2)cobalt_thread_shadow
在这里插入图片描述
第676行,pthread_create 函数是 Cobalt 实时扩展中用于创建新线程的核心函数。它负责为新的线程结构体 (struct cobalt_thread) 分配内存,初始化线程的基本属性(如名称、标志、亲和性等)到 iattr 结构体中,调用 xnthread_init 函数初始化线程对象,插入struct cobalt_process中thread_list链表!初始化完成后,线程处于休眠状态,直到通过 xnthread_start() 显式启动。

第680行,cobalt_map_user用于将一个 Xenomai 线程映射到当前运行在用户空间的普通 Linux 任务。这个过程称为“影子线程上下文”(shadow thread context)创建,具体是调用pipeline_init_shadow_tcb完成的,例如cobalt_thread.threadbase.tcb.core中的struct task_struct *host_task指向Linux 任务task_struct结构体。在此之后,struct cobalt_thread称为struct task_struct的影子!最后,显示调用xnthread_start,启动线程。

第693行,xnthread_harden用于将当前运行的 Linux 任务迁移到 Xenomai 域。这个过程通常称为“硬化”(hardening),它使得当前任务从标准 Linux 调度器切换到 Xenomai 实时调度器,并在 head域中继续执行。

至此,Xenomai/Linux进程/主线程描述符之间的关联完全建立完毕,且struct cobalt_thread称为struct task_struct的影子。

点击查看《Xenomai/IPIPE源代码情景解析》
原创不易,需要大家多多鼓励!您的关注、点赞、收藏就是我的创作动力!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值