📄 linux源代码的注释.txt
字号:
控制块的内容,具体做法是先直接将其父进程的进程控制块的内容复制过来,再在
后面对需要更新的部分做一些必要的赋值 */
retval= -EAGAIN;
if(atomic_read(&p->user->processor) >= p->rlim[RLIMIT_NPROC].
rlim_cur)
goto bad_fork_free;
atomic_inc(& p->user->_count);
atomic_inc(& p->user->processes);
/* 上面代码的意思: 如果父亲进程已经用了用户进程,则修改p->user->_count和
p->user->processes,将其数目加1,当然除非用户进程的 RLIMIT_NPROC
已经超过额定数目,如果你对代码不理解,那就先不要理解了,等你学完后面的代码
时就能理解了*/
if(nr_threads >= max_threads)
goto bad_fork_cleanup_count;
/* 上面的代码的意思是: 如果计算机中的进程的最大的进程数大于系统限定的最大
数目就返回错误信号 */
get_exec_domain(p->exec_domain);
if(p->binfmt && p->binfmt->module)
p->did_exec=NULL;
p->swappable=NULL;
p->state = TASK_UNINTERRUPTIBLE;
/ * 上面的代码比较简单: 其中p是指向进程控制块task_struct的指针,did_exec
和swappable以及state都在进程控制块中有定义,是对进程的这三个属性
进行赋值,其意思如下:
did_exec标志的意思是: 此进程是否被执行.
swappable标志的意思是: 此进程占有的内存页面是否可以被换出到交换空间.
state在前面有讲过.
那么上面代码的意思是刚创建的进程没有被执行并且内存空间页面不可以被换
出内存,当前状态设置为不可打断睡眠状态 */
copy_flags(clone_flags, p);
p->pid = get_pid(clone_flags);
/ * 上面代码涉及到进程控制块中的进程标志flags,在 task_struct中有定义,flags
的意思是进程中有一些特殊的时候要靠它来决定进程调度函数的调度,
上面的意思是: 将传进来的参数clone_flags通过copy_flags()函数转化为子进程
的进程标志flags, 然后为新的子进程创建一个进程标志符pid */
p->run_list.next=NULL;
p->run_list.prev=NULL;
/ * 对进程队列run_list进行初始化,进程队列run_list以后将 */
if((clone_flags & CLONG_VFORK) || ! (clone_flags & CLONG_PARENT))
{
p->p_opptr = current;
if(! (p->ptrace & PT_PTRACED))
p->p_pptr = current;
}
/ * 前面我们说过创建新进程的系统调用函数有三个,分别是sys_fork,sys_vfork,
sys_clone.
上面的意思是: 如果使用的sys_vfork()函数调用创建函数或者传人的参数
clone_flags的CLONE_PARENT位为1,则将子进程的的p_opptr()指针
指向当前进程.其中p_opptr指针在进程控制块task_struct中有定义,意思
是它指向进程的祖先进程.如果ptrace的PT_PTRACED不为1,则将进程的
指向父进程的指针指向当前进程.其中p_pptr是进程指向其父亲进程的指针,
同样在进程控制块task_struct中有定义 * /
p->p_cptr = NULL;
/ * 进程的p_cptr指针指向它的儿子进程,在这里初始化为NULL * /
init_waitqueue_head(&p->wait_chldexit);
/ * 意思是: 初始化等待队列,等待队列是就绪队列一个基础,等待队列的进程当它得到
它等待的资源(除CPU资源,CPUs是就绪队列中的进程等待的资源)后马上进入
就绪队列,等待调度函数的调用以获得CPU资源 * /
/ * 下面所以的代码都是对进程控制块task_struct一些变量做一些初始化,
这儿先就不过多的介绍了,现在只要知道有这些东西就行了 * /
p->vfork_sem=NULL;
spin_lock_inin(& p->alloc_lock);
p->sigpending = 0;
init_sigpending(& p->pending);
p->it_real_value = p->it_virt_value =p->it_prof_value = 0;
p->it_real_incr = p->it_virt_incr= p->it_prof_incr =0;
init_timer(&p->real_timer);
p->real_timer.data = (unsigned long) p ;
p->leader = 0;
p->tty_old_pgrd = 0;
p->times.tms_utime = p->times.tms_stimes = 0;
p->times.tms_cutime= p->times.tms_cstime = 0;
# ifdef CONFIG_SMP
{
int i;
p->has_cpu = 0;
p->proessor = current->proessor;
for(i=0; i p->per_cpu_utime[i] = p->per_cpu_stime[i] =0;
spin_lock_init(& p->sigmask_lock);
}
endif
p->lock_depth = -1;
p->start_time = jiffies;
/ * 初始化在此结束 */
retval = -ENOMEN;
if(copy_files(clone_flags, p))
goto bad_fork_cleanup;
if(copy_fs(clone_flags, p))
goto bad_fork_cleanup_files;
if(copy_sighand(clone_flags, p))
goto bad_fork_cleanup_fs;
if(copy_mm(clone_flags, p))
goto bad_fork_cleanup_sighand;
/ * 上面代码的意思是: 根据传人的参数clone_flags决定复制打开文件表,文件
系统信息,信号处理句柄和存储信息管理(上面4个分别代表的信息)还是直接
和父亲进程共享,仅仅将引用数加1 * /
retval = copy_thread(0, clone_flags, stack_start, stack_size, p, reps);
if(retval)
goto bad_fork_cleanup_sighand;
p->semundo = NULL;
p->parent_exec_id = p->self_exec_id;
p->swappable = 1;
p->exit_signal = clone_flags & CSIGNAL;
p->pdeath_signal = 0;
p->counter = (current->counter +1) >>1;
current->counter >>=1;
/ * 将父亲进程的时间片加1再除2然后赋值给子进程,同时将父亲进程的时间片
减半 * /
if(! current ->counter)
current->need_resched = 1;
/ * 如果父亲进程的时间片减半后为0的话,直接将need_resched设置为1,
need_resched在前面已经说过,它的意思是: 如果设置为1,下一此调度函数
可以直接调度这个进程,但是如果设置为0则表示下一次调度函数不能调度此
函数 */
retval = pid;
p->gpid = retval;
INIT_LIST_HEAD(&p->thread_group);
writh_lock_irq(&taslist_lock);
if(clone_flags & CLONE_THREAD)
{
p->tgid = current->tgid;
list_add(&p->thread_group, ¤t->thread_group);
}
SET_LINKS(p);
hash_pid(p);
nr_threads ++;
writh_unlock_irq(&tasklist_lock);
if(p->ptrace & PT_PTRACED)
send_sig(SIGSTOP, p, 1);
wake_up_Linux联盟收集整理
processor(p);
++ total_forks;
/ * 下面的前面goto代码要要转到执行的地方 */
fork_out:
if((clone_flags & CLONE_VFORK) && (retval >0))
down(&sem);
return retval;
bad_fork_cleanup_sighand:
exit_sighand(p);
bad_fork_cleanup_fs:
exit_fs(p);
bad_fork_cleanup_files:
exit_files(p);
bad_ford_cleanup:
put_exec_domain(p->exec_domain);
if(p->binfim && p->binfim->module)
bad_fork_cleanup_count:
atomic_dec(&p->user->processes);
free_uid(p->user);
bad_fork_free:
free_task_struct(p);
goto fork_out;
}
______________________________________________________________/kernel/fork.c
上面讲解了三个进程创建函数sys_fork, sys_clone, sys_vfork****同要调用的函数
do_fork(),下面讲一下这三个函数,其实这三个函数很简单
sys_fork()函数如下:
_______________________________________________/arch/i386/kernel/process.c
asmlinkage int sys_fork(struct pt_regs regs)
{
return do_fork(SIGCHLD, regs.esp, ®s, 0)
}
_______________________________________________/arch/i386/kernel/process.c
sys_clone()函数如下:_____________________________________________/arch/i386/kernel/process.c
asmlinkage int sys_clone(struct pt_regs regs)
{
unsigned long clone_flags;
unsigned long newsp;
clone_flags = regs.ebx;
newsp = regs.ecx;
if(! Newsp)
newsp = regs.esp;
return do_fork(SIGCHLD, regs.esp, ®s, 0)
}
_______________________________________________/arch/i386/kernel/process.c
sys_vfork()函数如下:
_______________________________________________/arch/i386/kernel/process.c
asmlinkage int sys_vfork(struct pt_regs regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0)
}
_______________________________________________/arch/i386/kernel/process.c
Linux联盟收集整理
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -