2023-2024-1 20232829《Linux内核原理与分析》第七周作业

1. task_struct 数据结构

task_struct 是 Linux 内核中表示进程的重要数据结构。它包含了有关进程状态、调度信息、文件系统信息等的详细信息。以下是对 task_struct 数据结构的一些主要字段:

struct task_struct {
    volatile long state;  // 进程状态
    void *stack;          // 进程堆栈指针
    unsigned int flags;   // 进程标志
    struct list_head tasks;  // 进程链表
    pid_t pid;            // 进程ID
    pid_t tgid;           // 进程组ID
    struct mm_struct *mm; // 内存管理结构
    struct files_struct *files;  // 文件描述符表
    // ... 其他字段和信息 ...
};

state(进程状态):表示进程的当前状态,可能是运行、睡眠、停止等。状态的改变反映了进程的活动。示例:long state;
pid(进程标识符):进程的唯一标识符。通过这个字段,内核可以追踪和管理进程。示例:pid_t pid;
parent(父进程指针):parent 字段指向父进程的 task_struct 结构。这是用于构建进程树的关键字段。示例:struct task_struct __rcu *parent;
children(子进程链表):children 是一个链表,包含指向当前进程的所有子进程的指针。这有助于实现进程之间的父子关系。示例:struct list_head children;
sibling(兄弟进程链表):sibling 是一个链表,包含指向与当前进程具有相同父进程的其他进程的指针。这是同一进程组的进程之间的链接。示例:struct list_head sibling;
comm(进程名):comm 字段包含了进程的名称。它是一个简短的字符串,用于标识进程。示例:char comm[TASK_COMM_LEN];
mm(内存管理):mm 字段指向描述进程内存布局和管理的结构。这包括进程的地址空间布局、页表等信息。示例:struct mm_struct *mm;
active_mm(当前地址空间):active_mm 字段指向当前进程正在使用的地址空间。在进程切换时,这个字段可能会改变。示例:struct mm_struct *active_mm;
group_leader(线程组领导):group_leader 字段指向线程组的领导进程。在多线程环境中,这有助于管理线程组。示例:struct task_struct __rcu *group_leader;
fs(文件系统信息):fs 字段包含有关进程打开的文件的信息。它指向 fs_struct 结构,其中包含有关文件系统的信息。示例:struct fs_struct *fs;
files(文件表):files 字段指向文件描述符表,它包含了进程打开的文件和其他 I/O 相关信息。示例:struct files_struct *files;
signal(信号处理):signal 字段包含有关进程信号处理的信息。信号是用于与进程通信和控制其行为的机制。示例:struct signal_struct *signal;
cred(安全凭证):cred 字段包含有关进程权限和身份的信息。这是与安全相关的关键信息。示例:struct cred __rcu *cred;
thread_info(线程信息):thread_info 字段包含了有关线程的低级信息,如堆栈指针和处理器状态。这对于线程管理是必要的。示例:struct thread_info thread_info;

2、分析 fork 函数对应的内核处理过程 sys_clone

fork 函数在Linux内核中的实现通常是通过 sys_clone 系统调用来完成的,sys_clone 是创建新进程的底层系统调用,该过程分析如下:

1.首先是fork触发系统调用sys_clone,然后最终执行的是do_fork。
2.fork创建了两个进程,一个父进程,一个子进程,其中子进程是对父进程的拷贝,它从父进程处复制了整个进程的地址空间,只有进程号和一些计时器等等是自己独有的,由于要复制很多资源,所以fork创建进程是很慢的。
3.fork执行一次有两次返回值,在父进程里返回新建的子进程编号,在子进程里返回0.由于创建进程的三种方式最终都是调用do_fork。
4.创建子进程的一个重要的过程是复制父进程里面的资源,有看到下面的copy_process函数,所以基本判断是复制资源的函数.这段代码是创建子进程的精华部分,所有的创建进程上下文,为新进程设置新的pid,还有复制代码,都在这一部分了。

3、使用gdb跟踪分析一个fork系统调用内核处理函数sys_clone ,验证对Linux系统创建一个新进程的理解

结果如图所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 总结

创建一个新进程在内核中的执行过程大致如下:

使用系统调用Sys_clone(或fork,vfork)系统调用创建一个新进程。这些系统调用会通过调用do_fork函数来实现进程的创建。Linux通过复制父进程的进程控制块(PCB)中的task_struct结构来创建一个新进程,并为新进程分配一个新的内核堆栈。需要修改复制过来的进程数据,例如进程ID(pid)、进程链表等。这一步通过执行copy_process和copy_thread函数来完成。设置新进程的内核栈顶,即p->thread.sp = (unsigned long) childregs。这个值表示当调度到子进程时,使用的内核栈的顶部位置。设置子进程的第一条指令地址,即p->thread.ip = (unsigned long) ret_from_fork。这个地址表示当调度到子进程时,执行的第一条指令。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值