现在的位置: 首页 > 综合 > 正文

Linux2.6进程的创建与删除

2013年10月05日 ⁄ 综合 ⁄ 共 1596字 ⁄ 字号 评论关闭

一、进程的创建

1.系统调用clone()与fork()的区别:

  资源的继承方式 参数 区分父进程与子进程的方法
fork() 全部复制,即父进程的所有资源全部通过数据结构的复制传给子进程 无参数 父进程与子进程,从fork()返回时的返回值不同,以此区分二者。子进程返回0.父进程返回子进程的pid
clone() 有选择地将资源复制给子进程,没有复制的资源通过指针复制的方式与子进程共享(共享与复制的关系见2) 有参数,用于设置资源复制的方式 clone()所产生的子线程的PID有可能是0,因此采用比较系统堆栈指针的方法来区分二者。

note:

(1)为什么返回值的方式对fork()适用?

因为fork()后子进程拥有独立的资源,是一个进程,有自己的独一无二的PID,不可能是0

(2)为什么返回的方式对clone()不适用?

因为clone()不一定复制资源,产生的有可能是一个线程。线程的PID与它所在的线程组的PID相同。如果父线程的PID是0,那么子线程的PID也是0。父与子的返回值是一样的,无法区分。

(3)为什么比较系统堆栈指针的方式对fork()不适用?

因为普通的进程都在用户空间,系统堆栈不知道在哪里

(4)为什么比较系统堆栈指针的方式对clone()适用?

每一个内核线程都有自己的系统空间堆栈,子线程的堆栈空间的指针必须与父线程不同

(5)它们最终都是调用do_fork()创建子进程的

note中的内容讲得不好理解,因为有几句话强调线程与进程的区别,有几句话里进程指的是进程或线程,如果结合Linux2.6进程-1中的表格,会有助于对note的理解


2.线程创建函数kernel_thread(),本质也是调用do_fork(),但是不复制进程的页表。因为新内核线程不会访问用户态地址空间


3.共享与复制的关系

(1)相同点:

复制完全之初,子进程有了一个副本,它的内容与父进程的正本内容基本相同。

(2)不同点-共享:

共享是指仅复制指针,是浅层复制。事实上,父与子都是对同一地址进程操作。

父与子并发地对同一堆栈区进行操作,这种行为是致命的。

通常的解决方法是:扣留父进程,只让子进程返回。当子进程有了自己的用户空间,或子进程确定不再使用父的用户空间(死亡)后,才能让父返回。

(3)不同点-复制:

互不干扰


4.所有用于创建子进程的系统调用,最终都是通过调用do_fork()创建子进程的

(1)获取一个空进程项

(2)获取一页内存

(3)自制当前进程的数据结构到内存中

(4)新进程设置为不可中断等待

(5)对新进程的数据结构修改

note:不分配物理内存,写时复制


5.写时复制

(1)将父进程的页面表项改为写保护

(2)把表项设置到子进程的页面表中

(3)当父进程或子进程企图写页面时,发生页面异常,给要写的进程另分配一个物理页面,此时才是真正的复制

(5)置两个页面都为可写


6.父进程创建子进程后,父进程剩余节拍数被划分为两等份,一份给父,一份给子。

一个进程不能通过创建多个后代来霸占资源


二、进程的撤消与删除

1.子进程被终止以后,不能立即删除,因为它可能还有父进程需要的信息。

只有父进程发出了与被终止进程相关的wait类系统调用后,才允许由父进程为子进程彻底删除


2.子进程在do_exit()的最后,会调用schedule()。这个函数的返回条件是再次被调度。但此进程再也不会被调度,因此schedule()不会返回,do_exit()也不会被返回

此时进程的状态是ZOMBIE,即调度被无限推迟,直到父进程收到信号后来处理后事,将其task_struct释放,这个进程就彻底消失了。


3.父进程要为子进程处理后事。

如果一个进程被终止前还有子进程,则要把子进程托付给某个进程。

如果父进程是一个线程组的成员,就把子进程托付给线程组的下一个成员。

否则就把子进程托付给0号进程


4.中断服务程序、软件中断服务程序、0号进程、1号进程不允许终止。

抱歉!评论已关闭.