Linux2.6内核进程创建过程分析(1)(2)
# define alloc_task_struct() kmem_cache_alloc(task_struct_cachep, GFP_KERNEL) |
接着分配thread_info结构空间
ti = alloc_thread_info(tsk);
thread_info结构定义在asm/thread_info.h中
struct thread_info { struct task_struct *task; struct exec_domain *exec_domain; unsigned long flags; unsigned long status; __u32 cpu; __s32 preempt_count; mm_segment_t addr_limit; struct restart_block restart_block; unsigned long previous_esp; __u8 supervisor_stack[0]; }; |
继续
*tsk = *orig;
为整个task_struct结构复制
再调用setup_thread_stack()函数为thread_info结构复制
static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) { *task_thread_info(p) = *task_thread_info(org); task_thread_info(p)->task = p; } |
其中
task_thread_info(p)->task = p;
thread_info结构中的task成员中存放的是指向当前进程task_struct结构的指针。
回到copy_process()函数,继续看:
if (atomic_read(&p->user->processes) >= p->signal-> rlim[RLIMIT_NPROC].rlim_cur) { if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && p->user != &root_user) goto bad_fork_free; } atomic_inc(&p->user->__count); atomic_inc(&p->user->processes); get_group_info(p->group_info); |
首先看前面的两个if,第一个if里面的rlim数组包含在task_sturct数组中。对进程占用的资源数做出限制,rlim[RLIMIT_NPROC]限制了改进程用户可以拥有的总进程数量,如果当前用户所拥有的进程数量超过了规定的最大拥有进程数量,在2.4内核中就直接goto bad_fork_free了。第2个if使用了capable()函数来对权限做出检查,检查是否有权对指定的资源进行操作,该函数返回0则代表无权操作。该函数的定义在linux/capability.h中,其中包含了与之相对应的权限列表。
在task_struct结构中有一个指针user,该指针指向一个user_struct结构,一个用户的多个进程可以通过user指针共享该用户的资源信息,该结构定义在include/linux/sched.h中:
struct user_struct { atomic_t __count; /*统计用户拥有进程数量的计数器 */ atomic_t processes; /*统计用户拥有进程数 */ atomic_t files; /* 统计用户打开的文件数 */ atomic_t sigpending; /* 统计用户拥有的信号 */ #ifdef CONFIG_INOTIFY_USER atomic_t inotify_watches; /* How many inotify watches does this user have? */ atomic_t inotify_devs; /* How many inotify devs does this user have opened? */ #endif /* protected by mq_lock */ unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */ unsigned long locked_shm; /* How many pages of mlocked shm ? */ #ifdef CONFIG_KEYS struct key *uid_keyring; /* UID specific keyring */ struct key *session_keyring; /* UID's default session keyring */ #endif /* Hash table maintenance information */ struct list_head uidhash_list; uid_t uid; }; |
既然新创建了一个进程,自然要更新该用户的user_struct结构,累加相应的计数器,这个工作就由atomic_inc()函数完成,atomic_inc函数定义在include/asm-blackfin/atomic.h中:
static __inline__ void atomic_inc(volatile atomic_t * v) { long flags; local_irq_save(flags); v->counter++; local_irq_restore(flags); } |
函数保存当前各成员的标记,然后进行累加,最后更新各成员,完成累加计数器的操作。
继续看copy_process函数的代码:
if (nr_threads >= max_threads) goto bad_fork_cleanup_count; if (!try_module_get(task_thread_info(p)->exec_domain->module)) goto bad_fork_cleanup_count; if (p->binfmt && !try_module_get(p->binfmt->module)) goto bad_fork_cleanup_put_domain; p->did_exec = 0; delayacct_tsk_init(p); /* Must remain after dup_task_struct() */ copy_flags(clone_flags, p); p->pid = pid_nr(pid); retval = -EFAULT; if (clone_flags & CLONE_PARENT_SETTID) if (put_user(p->pid, parent_tidptr)) goto bad_fork_cleanup_delays_binfmt; INIT_LIST_HEAD(&p->children); INIT_LIST_HEAD(&p->sibling); p->vfork_done = NULL; spin_lock_init(&p->alloc_lock); clear_tsk_thread_flag(p, TIF_SIGPENDING); init_sigpending(&p->pending); |
代码段
if (nr_threads >= max_threads) goto bad_fork_cleanup_count; |
检查创建的进程是否超过了系统进程总量
if (!try_module_get(task_thread_info(p)->exec_domain->module)) goto bad_fork_cleanup_count; |
获得进程执行域
if (p->binfmt && !try_module_get(p->binfmt->module)) goto bad_fork_cleanup_put_domain; |
不同进程所执行的程序的格式也不一样,系统对不同格式的支持通过动态安装驱动模块实现,task_struct结构中有一个指向linux_binfmt结构的指针,获得进程执行程序映象。
copy_flags(clone_flags, p); |
调用copy_flags函数更新task_struct结构中flags成员。表明进程是否拥有超级用户权限的PF_SUPERPPRIV标志被清除,表明进程还没有exec()的PF_FORKNOEXEC被设置,相关实现代码也在fork..c中:
static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) { unsigned long new_flags = p->flags; new_flags &= ~(PF_SUPERPRIV | PF_NOFREEZE); new_flags |= PF_FORKNOEXEC; if (!(clone_flags & CLONE_PTRACE)) p->ptrace = 0; p->flags = new_flags; } |
接着p->pid = pid_nr(pid);获取一个PID
p->vfork_done = NULL; |
继续走下去:
p->utime = cputime_zero; p->stime = cputime_zero; p->sched_time = 0; #ifdef CONFIG_TASK_XACCT p->rchar = 0; /* I/O counter: bytes read */ p->wchar = 0; /* I/O counter: bytes written */ p->syscr = 0; /* I/O counter: read syscalls */ p->syscw = 0; ………………….. 开始漫长的对子进程task_struct结构的初始化 ………………….. ………………….. ………………….. ………………….. |
继续
p->tgid = p->pid; if (clone_flags & CLONE_THREAD) p->tgid = current->tgid; |
评论暂时关闭