URN Logo
UNIX Resources » Linux » China Linux Forum » Linux内核技术 » 第293页 » 新兵笔记--ULK(C3) Creating Processes
announcement 声明: 本页内容为中国Linux论坛的内容镜像,文章的版权以及其他所有的相关权利属于中国Linux论坛和相应文章的作者,如果转载,请注明文章来源及相关版权信息。
Resources
China Linux Forum(finished)
Linux Forum(finished)
FreeBSD China(finished)
linuxforum.com
  LinuxForum General Chat
  Linux Advocacy
  LinuxForum Polls
  Introductions
  Linux Kernel Support
  Patch Management
  Development Release
  Linux Programming
  Linux Security
  Linux Software
  Linux Hardware Problems
    Linux Video Problems
    Linux Sound Problems
  Linux Networking Support
  Linux Printing Support
  Linux Human Interface Devices Support
  Linux Data Storage Support
  Linux Applications Support
  Linux Installation Support
  Linux Laptops Support
  Linux Motherboard, Chipsets, CPU, Memory
  Miscellaneous
  Debian Linux Support
  Ubuntu Linux Support
  LiveCD Discussions
  Gentoo Linux Support
  Mandrake Linux Support
  Redhat / Fedora Linux Support
  Slackware Linux Support
  SuSE Linux Support
  CentOS Linux Support
  Linux Web Servers
  Linux DNS Servers
  Linux Database Servers
  Linux Email Servers
  Linux FTP Servers
  Linux Squid Proxy Server
  Linux Samba Help
  Linux cPanel Help
  Linux Ensim Help
  Linux Plesk Help
  Linux Webmin / Usermin Help
  Qmail Toaster Help
  Linux Games
  Windows Game Emulation
  Linux Discussions
  General Linux Discussions
  Red Hat Linux Discussions
  More Red Hat Linux Discussions
  Mandrake Linux Discussions
  Slackware Linux Discussions
  SuSE Linux Discussions
  Debian Discussions
  Samba Help
  Linux Security
  Linux Networking
  Gentoo Help
  Operating System Rant Forum
  Hardware Rants
   
新兵笔记--ULK(C3) Creating Processes
新兵笔记--ULK(C3) Creating Processes - Big John [2001-05-29 17:36 | 5,290 byte(s)]
 
 
Re: 新兵笔记--ULK(C3) Creating Processes - jkl [2001-05-30 12:30 | 266 byte(s)]
 
Re: 新兵笔记--ULK(C3) Creating Processes - Big John [2001-05-31 15:34 | 586 byte(s)]
 
Re: 新兵笔记--ULK(C3) Creating Processes - lucian_yao [2001-05-29 21:39 | 184 byte(s)]
 
Subject: 新兵笔记--ULK(C3) Creating Processes
Author: Big John    Posted: 2001-05-29 17:36    Length: 5,290 byte(s)
[Original] [Print] [Top]
description:
创建一个进程我一直认为是很复杂的一件事情,它牵涉太多的东西,现在就提出来讲似乎早了点,我只感觉有点力不从心了。

不管怎样,还是开始吧,先让我们考虑了下fork一个进程需要进行的工作吧,最少它应该分配一个本章第一节中讲到的task_struct结构体;然后它还应该有一些父子关系,运行状态等东西是要满足的;最后,它和父进程有相同的内存结构,相同的代码,相同的文件,这些都是要解决的问题;还有一个小问题,父子进程同时从fork返回,但返回值不一样,相信每个用过fork的人都会知道了,如何实现的呢?

实际运行的问题远不止这些,还是来看代码吧,do_fork这个所有创建进程的入口,看它都解决了那些问题。

第一个问题是CLONE_PID,它好象会起多个process 0,这和多CPU有关,我就不关心它了。
然后是一个有关vfork的实现问题,vfork的含义为创建一个子进程,这个子进程和父进程共享地址空间,并且,父进程会阻塞在vfork的调用,直到子进程结束或执行一个新的程序父进程才能解除阻塞。Linux的实现如下:
1、struct semaphore sem = MUTEX_LOCKED; // 定义一个信号灯并初始化为已锁状态
2、current->vfork_sem = &sem; // 把信号灯赋到父进程的vfork_sem域中
3、if ((clone_flags & CLONE_VFORK) && (retval > 0)) // 如果是vfork调用,则父进程阻塞
down(&sem);
4、up(tsk->p_opptr->vfork_sem); // 解除父进程的vfork_sem信号灯
其中1-3是在do_fork中调用的,4是在mm_release中,想来进程结束或执行新的程序时会调用这个函数吧。

然后就是为子进程分配一个描述符并进行适当的初始化了。首先调用alloc_task_struct为子进程分配一个task_struct(这个函数在第一节中看到过),并进行一个“野蛮”的结构体值copy,把父进程的所有值copy到子进程的描述符中,由于是值copy,所以现在子进程的所有的指针都和父进程的指向相同的地方。然后调用find_empty_process在task数组中找一个空的位置并把它发进去。它还将调用get_pid得到一个进程号(这个看似简单的工作也是有说头的)。它的state会被初始化为TASK_RUNNING,并且它会由write_unlock_irq放到可运行队列中,它还将调用hash_pid函数把它挂进一个hash表pidhash中。它的起始时间将被置为jiffies,这是Linux的一个内部时间。当然,它还有一堆指针要置,一堆值要初始化,但这些应该是比较主要的了,也是我现在能理解的。

然后是一些资源环境的copy,文件描述符,进程路径,信号,虚存系统(也就是我说的线性地址空间),这些都有相应的clone_flag控制,你看每个函数的开头都会有的。具体情况就不讲了,否则这节就没完了。等我有时间或那位英雄有心情再把它补上吧。

然后是copy_thread函数,它是用来算是堆栈和tss段的,pt_regs是系统调时指向栈顶的一个结构,也就是说进程从do_fork调用返回用户态时,运行环境将从这里弹出。这里好象比较重要的是一个eax域吧,它被强行置0,好象就表示子进程退出时得到的返回值是0。然后是tss段的初始化,它的esp指向栈顶,它的eip指向ret_from_fork,这个东西在entry.s中,它是怎么用呢?我也没仔细看了。不过它的意思应该是当子进程得到CPU时,它马上就从do_fork返回到用户态。

还有一个counter域,这个值是用来计算进程的动态优先级的,
current->counter >>= 1;
p->counter = current->counter;
这样就是说父子进程平分这个counter值,它的潜意应该是说你不可能通过多创建进程来多获得CPU的时间,这样可以更公平对待所有进程。

还有就是一些比较杂的事了,比如 if (p->user) {
if (atomic_read(&p->user->count) >= p->rlim[RLIMIT_NPROC].rlim_cur)
goto bad_fork_free;
atomic_inc(&p->user->count);
是来判断当前用户创建的进程是否超出限制了,系统不会希望某个用户不停的创建进程的。这里要注意的是user是一个指针,如上所述,父子进程它们这个域指向的是同一个域。rlim是本章第一节的内容了。

if (p->exec_domain && p->exec_domain->module)
__MOD_INC_USE_COUNT(p->exec_domain->module);
if (p->binfmt && p->binfmt->module)
__MOD_INC_USE_COUNT(p->binfmt->module);
用来增加模块计数,可惜我还不知道它怎么用呢。

最后,来看看get_pid这个函数,它的作用是得到一个当前没有使用的pid。在Linux中,pid的值是从0到0x7fff之间。一般新进程使用的pid会是上一个最新进程的pid+1,但是这个pid可能已经超出Linux的允许范围,也许它另有一个进程在用。这样就需要另外选择了。Linux中是这样选择进程号的,它使用一个全局变量last_pid记录上次创建进程时用的进程号,还有一个静态变量next_safe用来记录从last_pid开始,下一个已被使用的最小的进程号。这样如果last_pid不超过next_safe,并且不超过表示范围(>0x7fff)的话,你都可以放心的分配进程了。如果last_pid超过范围,那么它会被置为300,原因是比这小的进程号可能被一些内核线程占用了。不过last_pid超过范围或超过next_pid的值时,last_pid和next_pid都会被重新计算,last_pid会不停的递增,然后遍觅进程链表,直到找到一个没有一个重复的进程号为止,同时next_safe也会和所有进程的pid比较,直到找到一个比last_pid大的最小的正在使用的进程号为止。

question:
要说问题似乎多了点,很多域都不知道是干什么用的,不过这些都待以后解决吧。
还有一个问题没想通:
p->state = TASK_UNINTERRUPTIBLE;
copy_flags(clone_flags, p);
p->pid = get_pid(clone_flags);
p->state = TASK_RUNNING;
这段中为什么先把state置为TASK_UNINTERRUPTIBLE,经过copy_flags和get_pid才把它置为TASK_RUNNING呢?有什么原因吗?还是只是随便写写?

闲言:
上周有点忙,所以一直也没帖,真是对不起党对不起人民。:)

[Original] [Print] [Top]
Subject: Re: 新兵笔记--ULK(C3) Creating Processes
Author: lucian_yao    Posted: 2001-05-29 21:39    Length: 184 byte(s)
[Original] [Print] [Top]
党和人民已经非常感激你了。:-)

我们的
内核文档与源码学习
[Original] [Print] [Top]
Subject: Re: 新兵笔记--ULK(C3) Creating Processes
Author: jkl    Posted: 2001-05-30 12:30    Length: 266 byte(s)
[Original] [Print] [Top]
CLONE_PID是内核初始化线程用来建立各个CPU的idle线程之用,2.2中do_fork()不将这些pid=0的子线程唤醒,而让它们保持在TASK_RUNNING状态。在2.4中有所变化,已经看不到"p->state = TASK_RUNNING"这一行了,所有的子线程都被唤醒。



[Original] [Print] [Top]
Subject: Re: 新兵笔记--ULK(C3) Creating Processes
Author: Big John    Posted: 2001-05-31 15:34    Length: 586 byte(s)
[Original] [Print] [Top]
我明白了,也就是说每个CPU会有一个pid为0的idle进程,并且所有的idle进程都形成一个自环
p->state = TASK_RUNNING;
p->next_run = p;
p->prev_run = p;
但它们不被wake_up_process唤醒。
retval = p->pid;
if (retval) {
。。。
wake_up_process(p);
}
对吧。

但是init好说,自已就是可运行队形的头,所以它不用wake_up的,但其它的idle进程呢?难道它们就一直这样自环着了?
本来不打算接触多CPU,但还是很好奇。

[Original] [Print] [Top]
Subject: Re: 新兵笔记--ULK(C3) Creating Processes
Author: coldsnowice    Posted: 2003-08-10 22:51    Length: 802 byte(s)
[Original] [Print] [Top]
p->state = TASK_UNINTERRUPTIBLE;
copy_flags(clone_flags, p);
p->pid = get_pid(clone_flags);
p->state = TASK_RUNNING;
这段中为什么先把state置为TASK_UNINTERRUPTIBLE,经过copy_flags和get_pid才把它置为TASK_RUNNING呢?有什么原因吗?还是只是随便写写?


之所以把 p->state 置为 TASK_UNITERRUPTIBLE是因为 get_pid() 是一个独占的操作,在这个过程中,有可能一时进不了临界区,所以只好先把 state 设为 这样了!仔细看一看 get_pid的代码就知道了



我有一个问题是关于0 号和 1号进程的。

0 号进程是在 start_kernel 时捏造出来的,在系统启动之后就成为了 idle( )了,而1 号进程是在 kernel_thread( ) 产生的,名字为int ,runqueue 是以 init 进程为队列头的,不知道我的理解对不对啊
[Original] [Print] [Top]
« Previous thread
核心中内存访问是否要进行页表转换?
Linux内核技术
293
Next thread »
关于内核升级的问题?
     

Copyright © 2018 UNIX Resources Network, All Rights Reserved.    About URN | Privacy & Legal | Help | Contact us