您的位置:首页 > 运维架构 > Linux

Linux学习记录之进程(一)

2012-07-16 19:56 239 查看
进程是Unix操作系统的最重要的抽象之一,它是处于执行期的程序,但是它不仅仅包括代码,还包括相关的文件,挂起信号等资源。线程是进程活动的对象,每个线程都有一个程序计数器,进程栈和一组进程计数器。Linux中线程是进程的一种特例。

进程提供两种虚拟机制,虚拟处理器和虚拟内存。

Linux系统中通过fork()系统调用来产生新的进程,产生的方式是复制当期的进程来产生新进程,所以调用fork()的进程称为父进程,新产生的进程被称为子进程。Linux系统中fork()是调用clone()这个系统调用。

1、进程描述符及任务结构

内核进程放在一个角task_list的双向循环链表里,每一个节点都是一个task_struct,称为进程描述符,该结构定义在<linux/sched.h>中。task_struct包含了描述一个进程的完整信息。

1.1分配进程描述符

Linux通过slab分配器来分配task_struct结构,这样能达到对象复用和缓存着色,(通过预分配和重复使用task_struct,可以避免动态分配和释放所带来的资源消耗,从而使得进程创建的速度较快)。现在不需要专门的寄存器,只需要在栈底放一个thread_info,这个struct可以方便快速计算出task_struct所在位置。

1.2进程描述符的存放

Linux为每个进程分配了一个PID,实际是个int类型,其默认最大值为32768,内核把每个进程的PID放在进程描述符中。这个值越小,转一圈的时间就越快。如果需要,可以修改/proc/sys/kernel/pid_max里的内容来修改最大值。

1.3进程的状态



1.4设置状态

内存需要经常设置进程的状态,这时候可以调用set_task_state(tast,state)函数来设置。

1.5进程上下文

在用户态执行的进程在系统调用和发送异常时会进入内核态,这时内核就成为代表程序运行的的进程上下文。

1.6进程家族树

Linux进程具备继承关系,所有的继承都是PID为1的init进程的后代。内核在系统启动的最后节点启动init进程,该进程读取初始化脚本,并执行其他的相关程序,最终完成系统启动的整个过程。每个task_struct都包含一个parent节点的指针和一个children的链表。

2进程创建

许多其他的操作系统都提供了产生集成的机制,首先在地址空间里创建进程,读入可执行文件,最后开始执行。Unix采用了与众不同的实现方式,它把上述步骤分解到两个单独的函数中去执行:fork()和exec()函数族。首先,fork()通过拷贝当期进程创建一个子进程。子进程与父进程的区别仅仅在于PID、PPD和默写资源和统计里。exec()函数负责拂去可执行文件并将其载入地址空间开始运行。

2.1写时拷贝

Linux的fork()使用写时拷贝页实现。写时拷贝可以推迟甚至免除拷贝数据。内核此时不复制整个进程的地址空间,二是让父进程和子进程共享一个拷贝。还有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。而一般情况下,fork()之后立即调用exec(),它们就无需复制了,fork()的实际开销就是复制父进程的页表及自己吃创建唯一的基础描述符。在一般情况下,进程创建后都会马上运行一个可执行文件,这种优化可以避免拷贝大量根本就不会被使用的数据。

2..2 fork()

fork()通过clone()系统调用实现,clone()调用do_fork(),do_fork完成大部分工作,它定义在kernel/fork.c文件中。该函数调用copy_process()函数,然后让进城开始执行。copy_process()函数完成的工作:

1、调用dup_task_struct()为新进程创建一个内核栈,threa_info结构和task_struct,这些值与当期进程值形同。连进程描述符也是完全相同。

2、检测新创建的这个子进程后,当期用户所拥有的进程数目有没有超过最大值。

3、现在,进程着手是自己与父进程区别开。进程描述符内的许多成员都要被请0或设置为初始值。进程描述符的成员值不是继承而来的,而主要是统计信息。进程描述符中大多数数据都是共享的。

4、接下来,子进程的状态被设置为TASK_UNINTERRUPTEBLE以保证她不会投入运行。

5、copy_process()调用copy_flags()以更新task_struct的flags成员。表面进程是否拥有超级用户权限的PF_SUPERRIV标志被请0.表明进程还没有调用exec()函数的PF_FORKNOEXEC标志被设置。

6、调用get_pid()为新进场获取一个有效的PID。

7、根据传递给clone()的参数标志,copy_process()拷贝或共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间等。在一般情况下,这些资源会被给定的进程的左右进程共享;否则,这些资源对每个进程是不同的,因此被拷贝到这里。

8、让父进程和子进程评分剩余的时间片。

9、最后,copy_process()函数作搜啊为欧诺工作,并返回一个指向子进程的指针。

最后回到do_fork()函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: