Linux中fork系统调用的源码剖析
2018-01-30 19:46
525 查看
[align=center]Linux中fork系统i调用的源码剖析[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]首先 先给大家看一张图 系统的看一下大概的fork的主要流程[/align]
[align=left]
[/align]
[align=left]上述图片中 最后eax寄存器置0 这个就是最后为什么子进程的返回值是0的理由[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]下面 就来浅谈一下 fork源码[/align]
[align=left]long do_fork(unsigned long clone_flags,[/align]
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
先说这几个参数:<
4000
/span>
(1)clone_flags:应该是标志位有选择的复制父进程
(2)stack_start:堆栈的起始地址
(3)regs:结构体指针上面说的是指向通用寄存器的值。是在从用户态切换到内核态时被保存到内核态堆栈中的
(4)stack_size:堆栈的大小
(5)parent_tidptr:存放父进程pid的指针(地址)
(6)child_tidptr:存放父进程pid的指针(地址)
具体的实现步骤:
1、
定义了一个结构体指针 struct task_struct *p 应该是接受子进程的pid
long pid = alloc_pidmap();这应该是给子进程分配pid
If(pid < 0)
return -EAGAIN; 这应该是判断子进程的pid是否分配成功
2、检查进程是否被跟踪
如果父进程被跟踪就要判断子进程是否被跟踪
如果子进程不是内核进程就设置CLONE_PTRACE标志
3、通过copy_process复制进程描述符
4、判断通过copy_process是否执行成功
if (!IS_ERR(p)):如果不是错误的 意思就是如果成功
struct completion vfork;定义一个结构体变量vfork completion有完成的意思
那就是定义了一个完成量vfork
if (clone_flags & CLONE_VFORK):如果clone_flags标志位有CLONE_VFORK
p->vfork_done = &vfork;让进程描述符p->vfork_done指向vfork
init_completion(&vfork);初始化这个vfork
5、
if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)):如果子进程被跟踪或者
clone_flags标志位有CLONE_STOPPED
sigaddset(&p->pending.signal, SIGSTOP);通过sigaddset函数给子进程发送SIGSTOP信号
set_tsk_thread_flag(p, TIF_SIGPENDING);这个不懂
6、
if (!(clone_flags & CLONE_STOPPED)):如果子进程的
c9bf
clone_flags标志位没有CLONE_STOPPED这个标志
wake_up_new_task(p, clone_flags);调用wake_up_new_task函数
else
p->state = TASK_STOPPED;如果CLONE_STOPPED标志被设置,就把子进程设置为TASK_STOPPED状态
7、如果父进程被跟踪,则将子进程的pid赋值给父进程的pstrace_message字段。
调用ptrace_notify()这个函数可以使当前进程停止 并向当前进程的父进程发送SIGCHLD信号
8、
if (clone_flags & CLONE_VFORK):如果clone_flags标志位有CLONE_VFORK标志
wait_for_completion(&vfork);调用wait_for_completion()函数
这个函数是干嘛的
if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
9、
如果copy_process()在执行的时候发生错误了 就先释放已分配的pid再让PTR_ERR()的返回值得到错误码赋值给pid
最后返回pid
[align=left][/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]首先 先给大家看一张图 系统的看一下大概的fork的主要流程[/align]
[align=left]
[/align]
[align=left]上述图片中 最后eax寄存器置0 这个就是最后为什么子进程的返回值是0的理由[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]下面 就来浅谈一下 fork源码[/align]
[align=left]long do_fork(unsigned long clone_flags,[/align]
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
先说这几个参数:<
4000
/span>
(1)clone_flags:应该是标志位有选择的复制父进程
(2)stack_start:堆栈的起始地址
(3)regs:结构体指针上面说的是指向通用寄存器的值。是在从用户态切换到内核态时被保存到内核态堆栈中的
(4)stack_size:堆栈的大小
(5)parent_tidptr:存放父进程pid的指针(地址)
(6)child_tidptr:存放父进程pid的指针(地址)
具体的实现步骤:
1、
定义了一个结构体指针 struct task_struct *p 应该是接受子进程的pid
long pid = alloc_pidmap();这应该是给子进程分配pid
If(pid < 0)
return -EAGAIN; 这应该是判断子进程的pid是否分配成功
2、检查进程是否被跟踪
如果父进程被跟踪就要判断子进程是否被跟踪
如果子进程不是内核进程就设置CLONE_PTRACE标志
3、通过copy_process复制进程描述符
4、判断通过copy_process是否执行成功
if (!IS_ERR(p)):如果不是错误的 意思就是如果成功
struct completion vfork;定义一个结构体变量vfork completion有完成的意思
那就是定义了一个完成量vfork
if (clone_flags & CLONE_VFORK):如果clone_flags标志位有CLONE_VFORK
p->vfork_done = &vfork;让进程描述符p->vfork_done指向vfork
init_completion(&vfork);初始化这个vfork
5、
if ((p->ptrace & PT_PTRACED) || (clone_flags & CLONE_STOPPED)):如果子进程被跟踪或者
clone_flags标志位有CLONE_STOPPED
sigaddset(&p->pending.signal, SIGSTOP);通过sigaddset函数给子进程发送SIGSTOP信号
set_tsk_thread_flag(p, TIF_SIGPENDING);这个不懂
6、
if (!(clone_flags & CLONE_STOPPED)):如果子进程的
c9bf
clone_flags标志位没有CLONE_STOPPED这个标志
wake_up_new_task(p, clone_flags);调用wake_up_new_task函数
else
p->state = TASK_STOPPED;如果CLONE_STOPPED标志被设置,就把子进程设置为TASK_STOPPED状态
7、如果父进程被跟踪,则将子进程的pid赋值给父进程的pstrace_message字段。
调用ptrace_notify()这个函数可以使当前进程停止 并向当前进程的父进程发送SIGCHLD信号
8、
if (clone_flags & CLONE_VFORK):如果clone_flags标志位有CLONE_VFORK标志
wait_for_completion(&vfork);调用wait_for_completion()函数
这个函数是干嘛的
if (unlikely (current->ptrace & PT_TRACE_VFORK_DONE))
ptrace_notify ((PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP);
9、
如果copy_process()在执行的时候发生错误了 就先释放已分配的pid再让PTR_ERR()的返回值得到错误码赋值给pid
最后返回pid
[align=left][/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
[align=left]
[/align]
相关文章推荐
- 《第一篇 从linux 0.11系统初始化main.c的fork()函数调用分析内核源码》
- linux: fork系统调用实现剖析
- fork系统调用底层实现源码剖析
- 【源码剖析】LINUX下的系统调用
- 【Linux 内核网络协议栈源码剖析】系统网络协议栈初始化及数据传输通道建立过程
- linux 内核源码 系统调用宏定义
- Linux 内核学习——系统调用(fork)
- 在linux2.6.39源码中添加一个简单的系统调用
- 一道关于Linux系统下fork系统调用的面试题
- linux2.6.9 poll系统调用源码分析
- 秒杀linux下系统调用fork()面试题
- linux内核剖析---Linux系统调用详解(实现机制分析)
- Linux-2.6.25 select系统调用源码分析
- linux-kernel 3.5.3Tcp系统调用,源码分析4-inet_init
- Linux操作系统基础理论(2)----fork系统调用
- linux系统调用fork()总结(二)
- Linux中fork系统调用
- linux系统下 fork()系统调用: 关于父子进程缓存问题的小坑
- linux-kernel 3.5.3Tcp系统调用,源码分析5-原子操作
- Linux系统进程控制编程(二)——fork系统调用