Linux中进程和线程的关系

进程创建

许多其他的操作系统产生进程的机制为:在新的地址空间里创建进程,读入可执行文件,最后开始执行。而Unix产生进程的方式不同,Unix通过两个函数fork()和exec()来实现上述过程。首先,fork()通过拷贝当前进程创建子进程。子进程与父进程区别仅仅在于PID和某些资源和统计量。exec()函数负责读取可执行文件并将其载入地址空间开始运行。

fork()

Linux通过clone()系统调用实现fork()。clone()根据fork()调用时传入的参数选择调用do_fork()。

do_fork()完成了创建中的大部分工作,该函数调用copy_process()函数,然后让进程开始运行。copy_process()函数过程如下:

1)调用dup_task_struct为新进程创建一个内核栈、thread_info结构和task_struct结构,这些值与当前进程的值相同。此时,子进程和父进程的描述符完全相同。

2)检查并确保新创建的子进程后,进程数目没有超出给它分配的资源的限制。

3)子进程开始与父进程产生区别。进程描述符内的许多成员都要被清零或设为初始值。task_struct中的大多数数据都依然未被修改。

4)子进程的状态被设置为TASK_UNINTERRUPTIBLE,以保证它不会被投入运行。

5)copy_process()调用copy_flag()以更新task_struct的flag成员。表明进程还没有调用exec()函数的PF——FORKNOEXEC标志被设置。

6)调用alloc_pid()为新进程分配一个有效的PID。

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

8)最后,copy_process()做扫尾工作并返回一个指向子进程的指针。

在回到do_fork()函数,如果copy_process()函数成功返回,新创建的子进程被唤醒并让其投入运行。

线程创建

Linux实现线程的机制非常独特。从内核的角度来说,它并没有线程这个概念。Linux把所有的线程都当作进程来实现。线程仅仅被视为一个与其他进程共享某些资源的进程。每个进程都拥有唯一隶属于自己的task_struct,所以在内核中,它看起来就像是一个普通的进程。

其他诸如Windows系统都有专门支持线程的机制(称作“轻量化进程”),而对于Linux来说,它只是一种进程间共享资源的手段。例如:有一个包含四个线程的进程,在提供专门线程支持的系统中,通常会有一个包含指向四个不同线程的指针进程描述符。该描述符负责描述想地址空间、打开的文件这样的共享资源。线程本身再去描述它占用的资源。相反,Linux仅仅创建四个进程并分配四个普通的task_struct结构。建立四个进程时指定他们共享某些资源。

线程的创建和普通进程的创建类似,只不过在调用clone()的时候需要传递一些参数标志来指明需要共享的资源:

clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND, 0);

作为对比,一个普通fork()的实现是:

clone(SIGCHLD, 0);

参数标志与含义关系:

CLONE_VM : 父子进程共享地址空间

CLONE_FS : 父子进程共享文件系统信息

CLONE_FILES : 父子进程共享打开的文件

CLONE_SIGHAND : 父子进程共享信号处理函数及被阻断的信号

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值