前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《Linux内核分析》之分析fork函数对应的系统调用处理过程

《Linux内核分析》之分析fork函数对应的系统调用处理过程

作者头像
WindCoder
发布2018-09-20 11:18:19
1K0
发布2018-09-20 11:18:19
举报
文章被收录于专栏:WindCoderWindCoder

实验过程

实验过程

1、在实验楼中shell终端依次执行如下代码:

代码语言:javascript
复制
cd LinuxKernel

rm -rf menu

git clone https://github.com/mengning/menu.git

cd menu

mv test_fork.c test.c

make rootfs

可看到启动后的MenuOS已经包含了fork命令。

2、通过增加-s -S启动参数打开调试模式

①其中在之前代码基础上先通过

代码语言:javascript
复制
 cd ..

返回上一级目录

②再执行如下代码打开调试模式,若无步骤①会提示找不到相关文件

代码语言:javascript
复制
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

3、打开gdb进行远程调试

①相关配置

代码语言:javascript
复制
gdb

file linux-3.18.6/vmlinux

target remote:1234

②设置断点

代码语言:javascript
复制
b sys_clone

b do_fork

b dup_task_struct

b copy_process

b copy_thread

b ret_from_fork

代码及分析

tast_struct

xref: /linux-3.18.6/include/linux/sched.h

代码语言:javascript
复制
struct task_struct {
    volatile long state;        //说明了该进程是否可以执行,还是可中断等信息
    unsigned long flags;        //进程号,在调用fork()时给出
    int sigpending;             //进程上是否有待处理的信号
    mm_segment_t addr_limit;    //进程地址空间,区分内核进程与普通进程在内存存放的位置不同
                                //0-0xBFFFFFFF for user-thead
                                //0-0xFFFFFFFF for kernel-thread
    //调度标志,表示该进程是否需要重新调度,若非0,则当从内核态返回到用户态,会发生调度
    volatile long need_resched;
    int lock_depth;             //锁深度
    long nice;                  //进程的基本时间片
    //进程的调度策略,有三种,实时进程:SCHED_FIFO,SCHED_RR, 分时进程:SCHED_OTHER
    unsigned long policy;
    struct mm_struct *mm;       //进程内存管理信息
    int processor;
    //若进程不在任何CPU上运行, cpus_runnable 的值是0,否则是1 这个值在运行队列被锁时更新
    unsigned long cpus_runnable, cpus_allowed;
    struct list_head run_list;  //指向运行队列的指针
    unsigned long sleep_time;   //进程的睡眠时间
    //用于将系统中所有的进程连成一个双向循环链表, 其根是init_task
    struct task_struct *next_task, *prev_task;
    struct mm_struct *active_mm;
    struct list_head local_pages;       //指向本地页面
    unsigned int allocation_order, nr_local_pages;
    struct linux_binfmt *binfmt;        //进程所运行的可执行文件的格式
    int exit_code, exit_signal;
    int pdeath_signal;                  //父进程终止是向子进程发送的信号
    unsigned long personality;

    int did_exec:1;
    pid_t pid;                          //进程标识符,用来代表一个进程
    pid_t pgrp;                         //进程组标识,表示进程所属的进程组
    pid_t tty_old_pgrp;                 //进程控制终端所在的组标识
    pid_t session;                      //进程的会话标识
    pid_t tgid;
    int leader;                         //表示进程是否为会话主管
    struct task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_osptr;
    struct list_head thread_group;      //线程链表
    struct task_struct *pidhash_next;   //用于将进程链入HASH表
    struct task_struct **pidhash_pprev;
    wait_queue_head_t wait_chldexit;    //供wait4()使用
    struct completion *vfork_done;      //供vfork() 使用
    unsigned long rt_priority;          //实时优先级,用它计算实时进程调度时的weight值
    …… //后面就不看了 我们不关心
};

进程创建分析

fork一个子进程的代码
代码语言:javascript
复制
#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、vfork和clone三个系统调用都可以创建一个新进程,而且都是通过调用do_fork来实现进程的创建;

Linux通过复制父进程来创建一个新进程,那么这就给我们理解这一个过程提供一个想象的框架:

复制一个PCB——task_struct

代码语言:javascript
复制
err = arch_dup_task_struct(tsk, orig);

要给新进程分配一个新的内核堆栈

代码语言:javascript
复制
ti = alloc_thread_info_node(tsk, node);
tsk->stack = ti;
setup_thread_stack(tsk, orig); //这里只是复制thread_info,而非复制内核堆栈
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实验过程
  • 代码及分析
    • tast_struct
      • 进程创建分析
        • fork一个子进程的代码
        •  创建一个新进程在内核中的执行过程
    相关产品与服务
    远程调试
    远程调试(Remote Debugging,RD)在云端为用户提供上千台真实手机/定制机/模拟器设备,快速实现随时随地测试。运用云测技术对测试方式、操作体验进行了优化,具备多样性的测试能力,包括随时截图和记录调试日志,稳定的支持自动化测试, 设备灵活调度,用例高效执行, 快速定位产品功能和兼容性问题。云手机帮助应用、移动游戏快速发现和解决问题,节省百万硬件费用,加速敏捷研发流程。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档