第六周: 进程的描述和进程的建立

吕松鸿 + 原创做品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000数据结构

1、进程的描述

1.操做系统三大功能:

进程管理
内存管理
文件系统

2.进程描述符task_struct数据结构

task _ struct:为了管理进程,内核必须对每一个进程进行清晰的描述,进程描述符提供了内核所需了解的进程信息。

进程的状态:Linux进程的状态(就绪态、运行态、阻塞态)

进程的标示pid:用来标示进程

3.Linux进程的状态

4.进程描述符task_struct数据结构:

struct task_struct {
volatile long state;    /* 进程的运行状态-1 unrunnable, 0 runnable, >0 stopped */
void *stack;    /*指定了进程的内核堆栈*/
atomic_t usage;
unsigned int flags; /* 每个进程的标识符 */
int on_rq;  /*运行队列*/
pid_t pid; /*进程标识符*/
struck list_head task;  /*进程链表*/
/*父子进程*/
struct task_struct __rcu *real_parent; /* real parent process */
struct task_struct __rcu *parent; 
struct list_head children;    /* list of my children */

2、进程的建立

建立进程的系统调用有3个,它们经过统一的系统调用接口进入核心态运行后就分道扬镳,各自调用本身的内核函数sys_fork、sys_clone、sys_vfork进行处理。这三个函数最终都是调用do_fork函数进行建立子进程的工做,只不过使用的参数有所不一样。
Linux经过复制父进程来建立一个新进程:复制父进程PCB--task_struct来建立一个新进程,要给新进程分配一个新的内核堆栈。
修改复制过来的进程数据,好比pid、进程链表等等执行copy_process和copy_thread。
以后,从ret_from_fork开始执行新进程。
#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");
    }
}

3、实验内容

1.删除menu,下载新代码并执行。

2.gdb调试

3.设置断点

4.单步追踪

4、总结

Linux经过复制父进程来建立一个新进程:复制父进程PCB--task_struct来建立一个新进程,要给新进程分配一个新的内核堆栈。

修改复制过来的进程数据,好比pid、进程链表等等执行copy_process和copy_thread。

设置sp调度到子进程时的内核栈顶,ip转到子进程时的第一条指令地址

以后,当子进程得到CPU的控制权开始运行的时候,ret _ form _ fork能够将后面的堆栈出栈,从iret返回到用户态,从而切换到子进程的用户空间,完成新进程的建立。
相关文章
相关标签/搜索