Linux进程相关知识点
Written with StackEdit中文版.
查看进程
进程ID:16位正整数,默认从2开始,ID为1的是init进程,它负责管理其他进程。** 父进程**:任何进程(除 init 进程)都是由另一个进程启动,该进程称为被启动进程的父进程,被启动的 进程称为子进程,父进程号无法在用户层修改。父进程的进程号(PID)即为子进程的父进程号 (PPID)。用户可以通过调用 getppid() 函数来获得当前进程的父进程号。
查看系统进程pspstree
进程状态
- 运行状态(就绪态和运行态) 表示进程在运行队列中,处于正在执行 或即将运行状态,只有在该状态的进程才可能在 CPU 上运行
- 可中断的睡眠状态(阻塞态) 处于这个状态的进程因为等待某种事件的发生而被挂起,比如进程 在等待信号。
- 不可中断的睡眠状态 通常是在等待输入或输出(I/O)完成,处于这种状态的进程不能响应异步信号。处于这 种状态的进程都是在等待输入或输出(I/O)完成,在等待完成后自动进入“就绪态”。
- 停止状态 通常是被 shell 的工作信号控制,或因为它被追踪,进程正处于调试器的控制之下。当进程收到 SIGSTOP 或者 SIGTSTP 中的其中一个信号时,进程状态会被置为暂停态, 该状态下的进程不再参与调度,但系统资源不会被释放,直到收到 SIGCONT 信号后被重新 置为就绪态。
- 退出状态(被回收) 正常退出:main 函数内 return 或者调用 exit() 函数或者线程调用 pthread_exit()
- 退出状态(僵尸进程)
- 僵尸进程是一种非常特殊的进程,它已经放弃了几乎所有的内存空间,没 有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等 信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。 调用 do_exit() 函数来使得进程的状态变成僵尸态
创建新进程
system()
- system() 函数是 C 标准库中提供的,它主要是提供了一种调用其它程序的简单方法。读者可 以利用 system() 函数调用一些应用程序,它产生的结果与从 shell 中执行这个程序基本相似。
fork()
- 创建一个新进程,父进程中fork调用返回新子进程的PID,子进程调用则返回0
- 使用 fork() 函数的本质是将父进程的内容复制一份,包括进程的地址空间,进程上下文、代码段,进程堆空间、栈空间,内存信息,进程的环境变量,标准 IO 的缓冲区等
- 子进程独有的内容为PID,记录锁,挂起的信号
exsc
- 系列函数主要是用于替换进程的执行程序,它可以根据指 定的文件名或目录名找到可执行文件,并用它来取代原调用进程的数据段、代码段和堆栈段,在 执行完之后,原调用进程的内容除了进程号外,其他全部被新程序的内容替换。
- fork和 exec 系列函数结合在一起使用就是创建一个新进程
终止进程
- 正常终止 从main返回调用exit(),_exit() _exit() 函数的作用:直接通过系统调用使进程终止运行exit() 函数在调用 exit 系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,即清除I/O缓冲。
- 异常终止 调用abort()由系统信号终止
等待进程
pid_t wait(int *wstatus);
- wait() 要与 fork() 配套出现,如果在使用 fork() 之前调用 wait(),wait() 的返回值则为-1,正 常情况下 wait() 的返回值为子进程的 PID
- 调用 wait() 或者 waitpid() 函数将僵尸进程回收,释放僵尸进程占有的内存空间,并且了解一下进程终止的状态信息。
- 子进程的结束状态信息会由参数 wstatus 返回,如果不在意子进程的结束状态信息,则参数 wstatus 可以设成 NULL
pid_t waitpid(pid_t pid, int *wstatus, int options);
- pid:指定要等待的子进程ID
- wstatus同上
- options:1. WNOHANG:如果 pid 指定的子进程没有终止运行,则 waitpid() 函数立即返回 0,而 不是阻塞在这个函数上等待;如果子进程已经终止运行,则立即返回该子进程的进程号与状态信息。2.WUNTRACED:如果子进程进入了暂停状态(可能子进程正处于被追踪等情况),则 马上返回。
- 如果一个进程有几个子进程,那么只要有一个子进程终止,wait就返回,而waitpid则可等待一个指定的进程。
进程类型
linux操作系统包括三种不同类型的进程:
- 交互进程:由shell启动的进程,既可在前台运行,也可在后台运行;
- 批处理进程:与终端没有联系,是一个进程序列;
- 守护进程:linux系统启动时启动的进程,并在后台运行;
批处理中的调度
先来先服务在这个算法中,一个单链表记录了所有就绪进程。要选取一个进程运行,只要从该队列的头部移走一个进程即可;要添加一个新的作业或者阻塞一个进程,只要把这个作业或进程附加在队列的末尾即可。最短作业优先假设我们已知运行时间,当输入队列有若干个同等重要的作业被启动时,调度程序应该使用最短优先作业算法最短剩余时间优先使用这个算法,调度程序总是选择剩余运行时间最短的那个进程运行。当一个新作业到达时,其整个时间同当前进程的剩余时间做比较。如果新的进程比当前运行进程需要更少的时间,当前进程就被挂起,而运行新的进程。
交互系统中的调度
轮询调度
:每个进程都会被分配一个时间段,称为时间片(quantum)
,在这个时间片内允许进程运行。如果时间片结束时进程还在运行的话,则抢占一个 CPU 并将其分配给另一个进程。如果进程在时间片结束前阻塞或结束,则 CPU 立即进行切换。优先级调度
:每个进程都被赋予一个优先级,优先级高的进程优先运行。但是也不意味着高优先级的进程能够永远一直运行下去,调度程序会在每个时钟中断期间降低当前运行进程的优先级。如果此操作导致其优先级降低到下一个最高进程的优先级以下,则会发生进程切换。或者,可以为每个进程分配允许运行的最大时间间隔。当时间间隔用完后,下一个高优先级的进程会得到运行的机会。最短进程优先
:根据进程过去的行为进行推测,并执行估计运行时间最短的那一个。假设每个终端上每条命令的预估运行时间为T0
,现在假设测量到其下一次运行时间为T1
,可以用两个值的加权来改进估计时间,即aT0+ (a- 1)T1
。通过选择 a 的值,可以决定是尽快忘掉老的运行时间彩票调度
:基本思想为进程提供各种系统资源的彩票
。当做出一个调度决策的时候,就随机抽出一张彩票,拥有彩票的进程将获得资源。比如在 CPU 进行调度时,系统可以每秒持有 50 次抽奖,每个中奖进程会获得额外运行时间的奖励。RR调度算法
:它是把所有进程按照一定的时间片轮流调度执行,每个进程只能执行一个时间片,当一个进程使用完时间片后,就被挂起,轮到下一个进程使用CPU。
进程间的通信方式
- 消息传递:消息传递是进程间实现通信和同步等待的机制,使用消息传递,进程间的交流不需要共享变量,直接就可以进行通信;消息传递分为发送方和接收方
- 先进先出队列:先进先出队列指的是两个不相关联进程间的通信,两个进程之间可以彼此相互进程通信,这是一种全双工通信方式
- 管道:管道用于两个相关进程之间的通信,这是一种半双工的通信方式,如果需要全双工,需要另外一个管道。
- 直接通信:在这种进程通信的方式中,进程与进程之间只存在一条链接,进程间要明确通信双方的命名。
- 间接通信:间接通信是通信双方不会直接建立连接,而是找到一个中介者,这个中介者可能是个对象等等,进程可以在其中放置消息,并且可以从中删除消息,以此达到进程间通信的目的。
- 消息队列:消息队列是内核中存储消息的链表,它由消息队列标识符进行标识,这种方式能够在不同的进程之间提供全双工的通信连接。
- 共享内存:共享内存是使用所有进程之间的内存来建立连接,这种类型需要同步进程访问来相互保护。
嵌入式相关知识 文章被收录于专栏
边学习边总结的嵌入式各种知识,八股,面经,量大管饱,最重要:免费开放,希望大家能共同进步。