unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
int __user *parent_tidptr,
int __user *child_tidptr)
先说这几个参数:
(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)):如果子进程的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