博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux中的进程
阅读量:4066 次
发布时间:2019-05-25

本文共 2126 字,大约阅读时间需要 7 分钟。

这篇文章算是自己最近学习Linux内核设计与实现的笔记, 主要是对学到的东西做一个总结, 让自己对知识的理解更加清晰.

 

进程是什么

进程就是处于执行期的程序.Linux的进程产生方式很特别, 被分解到了fork()和exec()两个系统调用中.

进程有时候也被称作任务(task),这是从进程调度的角度去看进程的. 如果是从资源管理的角度, 我们还是把它们叫做process.

线程和内核线程等又是什么

Linux将线程当作一种特殊的进程处理(个人觉得这是相当优雅的抽象).内核调度的对象是线程而不是进程. 每个线程有独立的程序计数器, 进程栈和一组进程寄存器.

内核线程是由kthread内核进程通过系统调用do_fork()创建的. 内核线程指向地址空间的mm指针被设置成NULL. 内核进程和普通进程一样, 可以被调度, 也可以被抢占.

每个进程都有自己的内核栈(一般为一页或两页内存大小, 默认为两页, 可配置). 通过在栈底创建一个struct thread_info结构. 对于x86来说, 通过栈指针就能计算出它的位置. 避免了使用另外的寄存器. (对于mips来说, 确实是使用的$28寄存器来保存该结构体指针的, 参见current_thread_info()宏的定义)

 

关于fork系统调用和进程创建

不管是进程, 线程, 还是内核线程, 最终都是通过传递不同的参数来调用do_fork()来完成的. 

Linux在用户调用fork之后, 会将一些页设置成只读状态,这样当发生页写入的事件的时候, 内核可以捕捉到异常, 这样通过相应的处理函数, 实现写时拷贝技术. 写时拷贝技术可以让创建进程的开销减少很多.

Fork()系统调用会从内核返回两次, 一次回到父进程, 一次回到新产生的子进程. 子进程会优先执行, 这是因为子进程一般会马上调用exec, 这样可以避免写时拷贝带来的额外开销.

内核把进程列表存放在tasklist双向循环链表中. 链表每一项为一个taskstruct(Linux的task struct结构通过slab分配器来分配, 以实现对象复用和缓存着色). 称之为processdescriptor(进程描述符). 

 

进程的状态和退出

进程描述符的state域描述了进程的当前状态, 有5种情况:TASK_RUNNING, TASK_INTERRUPTABLE(可中断睡眠),TASK_UNINTERRUPTIBLE(不可中断睡眠), TASK_TRACED(被调试), TASK_STOPPED(接收到SIGSTOP, SIGTSTP,SIGTTIN,SIGTTOUT等信号后).

进程退出执行后被设置为僵死状态,直到它的父进程调用wait或者waitpid为止.

进程退出时, 会将exit_state设置为EXIT_ZOMBIE状态, 进程最后会调用do_exit(), 然后do_exit()会调用schedule()切换到新的进程, 此后进程将不会再被调度.

父进程调用wait系统调用之后, 子进程的task_struct结构才会释放. 这样做是为了让父进程能够获取到子进程的退出状态(或者还有别的原因). 

 

进程调度和抢占

Linux从2.6.23版本之后, 使用CFS算法(完全公平调度算法)来对普通进程进行调度. CFS是针对普通进程的一种调度算法. 它使用红黑树来组织可运行进程的队列.

实时进程使用SCHED_FIFO或者SCHED_RR调度策略, 普通进程使用SCHED_NORMAL调度策略.

普通进程通过nice值(-20~+19)来确定优先级. 实时进程有实时进程的优先级(0~99). 默认情况下, nice值-20到+19对应的是从100到139的实时优先级范围.

 

我们称Linux是一种抢占式多任务系统. Linux同时支持用户抢占和内核抢占. 抢占可以让高优先级的进程更快的得到执行以满足实时性要求.

用户抢占发生在中断返回或者从系统调用返回用户空间的时候, 此时肯定是安全的. 

内核抢占发生在中断返回, 或者当前任务显示的调用schedule()或阻塞的时候, 或是内核代码再一次具有可抢占性的时候. (need_resched被设置, 且preempt_count为0, 即当前任务没有持有锁)

 

可中断睡眠与不可中断睡眠的区别

我们在等待信号量的时候, 可以选择调用down()或者down_interruptible()这两个api. 它们的区别是使用down()如果获取不到信号量则进程会进入到TASK_UNINTERRUPTIBLE状态, 而down_interruptiable会进入到TASK_INTERRUPTIBLE状态. 当进程进入TASK_INTERRUPTIBLE状态的时候, 是可以响应外部信号(通过kill或者其它方式发送的信号)的, 此时down_interruptiable会返回-EINTR, 但是信号量并没有被获取, 开发者需要自己做判断. 而处理TASK_UNINTERRUPTIBLE状态的进程则无法响应任何信号, 直到获取到信号量为止.

 

转载地址:http://iraji.baihongyu.com/

你可能感兴趣的文章
my read_Country
查看>>
OS + Linux File nfs / samba / rsync / inotify / smb / webdav
查看>>
RedHat + OS CPU、MEM、DISK
查看>>
project bbs_discuz
查看>>
net TCP/IP / TIME_WAIT / tcpip / iperf / cain
查看>>
Unix + OS books
查看>>
script webshell jspWebShell / pythonWebShell / phpWebShell
查看>>
project site_dns
查看>>
webServer kzserver/1.0.0
查看>>
project site_domain / dns / commerce
查看>>
my soft_macsoft
查看>>
hd printer lexmark / dazifuyin / dayin / fuyin
查看>>
OS + Unix IBM Aix basic / topas / nmon / filemon / vmstat / iostat / sysstat/sar
查看>>
monitorServer nagios / cacti / tivoli / zabbix / SaltStack
查看>>
my ReadMap subway / metro / map / ditie / gaotie / traffic / jiaotong
查看>>
OS + Linux DNS Server Bind
查看>>
JavaWeb capabilityTools / performanceTools
查看>>
net TCP/UDP SNMP / OidView / tcpdump
查看>>
my ReadPos / EAN
查看>>
my bike_mobiky / autobike / motobike / electrombile / electrocar
查看>>