2020-2021-1 20209318《Linux内核原理与分析》第七周作业
这个作业属于哪个课程 | <2020-2021-1Linux内核原理与分析)> |
---|---|
这个作业要求在哪里 | <2020-2021-1Linux内核原理与分析第七周作业> |
这个作业的目标 | <理解进程如何描述并分析进程创建> |
作业正文 | https://www.cnblogs.com/20209318zs/p/14020375.html |
进程的描述和进程的创建
进程的描述
在Linux内核中用数据结构struct task_struct 来描述进程
struct task_struct {
volatile long state; //进程状态
void *stack; // 指定进程内核堆栈
pid_t pid; //进程标识符
unsigned int rt_priority; //实时优先级
unsigned int policy; //调度策略
struct files_struct *files; //系统打开文件
...
}
进程描述符的结构示意图
Linux内核管理的进程状态转换图
阻塞态分为:
- TASK_INTERRUPTIBLE 状态可以被信号和 wake_up() 唤醒
- TASK_UNINTERRUPTIBLE 状态只能被 wake_up() 唤醒
进程的双向链表示意图
进程的创建
用户态创建进程的方法
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char * argv[])
{
int pid;
/* fork another process */
pid = fork();
if (pid < 0)
{
/* error occurred */
fprintf(stderr,"Fork Failed!");
exit(-1);
}
else if (pid == 0)
{
/* child process */
printf("This is Child Process!\n");
}
else
{
/* parent process */
printf("This is Parent Process!\n");
/* parent will wait for the child to complete*/
wait(NULL);
printf("Child Complete!\n");
}
}
fork系统调用把当前进程又复制了一个子进程,也就一个进程变成了两个进程,两个进程执行相同的代码,只是fork系统调用在父进程和子进程中的返回值不同。
分析Linux内核创建一个新进程的过程
依次执行下列命令
$ ls
$ cd ~/LinuxKernel
$ rm menu -rf
$ git clone https://github.com/mengning/menu.git
$ cd menu
$ mv test_fork.c test.c
$ make rootfs
编译运行出来可以看到列表中增加了一个fork
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -S -s
启动gdb,执行命令
$ file linux-3.18.6/vmlinux
$ target remote:1234
#设置断点
$ b sys_clone
$ b do_fork
$ b dup_task_struct
$ b copy_process
$ b copy_thread
$ b ret_from_fork
输入c继续运行内核程序
总结
本周主要学习了Linux创建子进程,并通过gdb分析调用过程。调用系统需在syscall_32.tbl中查找调用号,库函数sys_fork是用户态创建子进程的系统调用,也可能会使用sys_vfork、sys_clone系统调用,这三个系统调用都会使用do_fork函数。do_fork调用copy_process复制父进程的资源给子进程,copy_process中有各种函数进行复制初始化工作,完成各项工作之后会执行ret_from_fork,这是子进程的起点。