进程的简单理解

一、进程

  • Linux中,进程的产生是由用户空间程序进行系统调用fork()产生的,此函数会返回两次,一次回到父进程,一次回到新产生的进程。
  • 程序本身并不是进程,进程是处于执行期的程序以及相关的资源的总称。
  • 内核把进程的列表存放在叫做任务队列(task
    list)的双向循环链表中。链表中的每一项都是类型为task_struct,称为进程描述符的结构,进程描述符包含一个具体进程的所有信息:打开的文件,进程的地址空间,挂起的信号,进程的状态,内核内部数据,处理器状态。
  • 内核调度的对象是线程,不是进程,但是内核中对线程和进程并不特别区分。
  • task_struct结构一般是slab分配器分配的,只需要在栈顶(对于向上增长的栈来说)创建一个struct thread_info。对于current宏获取当前进程描述符采用的方法是通过current_thread_info()->task,而task中的state描述了进程的状态。
  • TASK_RUNNING状态表示进程可能正在执行,也可能处于就绪运行队列,进程中的所有状态都可变为终止状态。
  • 可执行程序代码是进程的重要组成部分。这些代码从一个可执行文件载入到进程的地址空间执行。一般程序在用户空间执行。当一个程序执行了系统调用或者触发了某个异常,它就陷入了内核空间。此时我们称内核“代表进程执行”并处于进程上下文中。在此上下文中current宏是有效的。除非在此间隙有更高优先级的进程需要执行并由调度器做出了相应调整,否则在内核退出的时候,程序恢复用户空间会继续执行。系统调用和异常处理是对内核明确定义的接口。进程只有通过这些接口才能陷入内核执行——对内核的所有访问都必须通过这些接口
  • Linux中进程存在一个明显的继承关系,所有的进程都是PID为1的init进程的后代。
  • 使用fork创建的子进程与与父进程的区别仅仅在于PID、PPID和某些资源及统计量。目前fork采用写时拷贝,此时并不赋值整个地址空间,而是先共享同一个拷贝。只有在写入的时候才会进行赋值,从而使各个进程拥有各自的拷贝,之前都是以只读共享。所以fork的开销很大,创建进程的速度也是很快。本意是要几乎拷贝父进程的所有,只是策略改变,需要的时候一个个拷贝即可。
  • fork返回两次,但是子进程会先执行,原因在子进程会立即执行exec()函数读取可执行文件并将其载入地址空间进行运行,可以避免写时拷贝的额外开销,如果父进程首先执行的话,有可能会开始向地址空间写入。

二、线程

  • 内核线程和普通的进程间的区别在于内核线程没有独立的地址空间(实际上指向地址空间的mm指针被设置为NULL)。它们值在内核空间运行,从来不切换到用户空间去。内核进程和普通进程一样,可以被调度,也可以被抢占。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值