Linux进程简述


父进程

自已创建一个或者多个进程

子进程

fork创建的。这个函数被调用一次但是返回两次,子进程返回0,父进程返回子进程id。

fork之后,操作系统会赋值一个与父进程完全相同的子进程,虽然是父子关系,但是更像是兄弟关系。这两个进程共享代码,但是数据空间是互相独立的,数据空间、指令、指针完全相同,子进程拥有当前父进程运行到的位置(PC相同)。

进程组

多个进程的集合,其中有一个组长,PID等于进程组的PGID,只要这个组里面有一个进程存在那么这个组就存在,与组长进程是否终止无关

作业

shell分前后台来控制的不是进程而是作业或者进程组。
一个前台作业由多个进程组成,一个后台也由多个进程组成。
shell可以运行一个前台作业和任意多个后台作业。这就是作业控制。

为什么只能运行一个前台作业?
前台作业是指当前终端窗口中运行的作业,而一个后台作业则是在后台运行的作业,不会占用当前终端窗口。
一个终端窗口只能有一个前台作业,是因为终端窗口只能和一个进程交互,用户在终端窗口输入命令,终端窗口会将命令传递给前台作业,如果有多个作业同时处于前台,那么输入的命令将被发送给哪个作业时不确定的,这会导致混乱和错误。

作业与进程组的区别

如果作业中有某个进程创建了子进程,则这个子进程是不属于该作业的,一旦作业运行结束,shell就把自己提到前台(子进程还在,但是子进程不属于作业)。如果原来的前台进程还存在(这个子进程还没有终止),他将自动变为后台进程组。

当我们在前台新起了一个作业,shell就被提到了后台,因此shell就没有办法再继续接受我们的指令并且解析运行了。 但是如果前台进程退出了,shell就会有被提到前台来,就可以继续接受我们的命令并且解析运行。

会话

是一个躲着多个进程组的集合。一个会话有一个控制终端,在xshell或者winscp中打开一个窗口就是新建一个会话。

孤儿进程

如果父进程退出,子进程还没有退出,那些子进程将成为孤儿进程。
孤儿进程被1号进程init进程收养。那么子进程的父进程将变成init进程。由init进程对他们完成状态收集工作。

僵尸进程

在操作系统中,当一个进程终止时,它的状态信息仍然被保留在系统中,直到其父进程调用wait或waitpid等系统调用来获取其终止状态信息。
如果父进程没有及时调用这些系统调用来获取终止状态信息,那么这个已经终止的子进程就会成为一个僵尸进程。
僵尸进程占用了系统资源,因为它们仍然占用了进程ID、进程表项和一些其他资源,而这些资源可能需要被其他进程使用。

Linux中,使用ps aux查看信息,发现僵尸进程状态为“Z”

当一个进程终止时,如果它的子进程仍然处于僵尸状态,那么这些子进程的父进程ID将被重置为1,也就是init进程。此时,init进程会调用wait或waitpid等系统调用来获取这些子进程的终止状态信息,并清除它们的僵尸状态,从而释放系统资源。

进程终止的几种方式

main函数自然返回
exit,属于C函数库
_exit,属于系统调用
调用abort函数,异常程序终止,同时发送SIGABRT信号给调用进程
接收能导致进程终止的信号 ctrl+c,SIGINT

如何让进程后台运行

命令后面加上&,这样是将命令放入到一个作业队列中
ctrl+z挂起进程,使用jobs查看序号,再使用bg%序号后台运行进程
nohup+&,将标准输出和标准错误缺省会被重定向到nohup文件中,忽略所有SIGHUP挂断信号
运行指令前面加上 setsid,使其父进程编程init进程,不受HUP信号影响
将命令+&放在()括号中,也可以是进程不受HUP信号影响

守护进程

指在后台运行的,没有控制终端与之相连的进程。
它独立于控制终端,周期性的执行某种任务。
Linux大多数服务器就是用守护进程的方式实现的,比如WEB服务器。
通过ps –x -j以查看作业控制信息,其中TPGID一栏为-1就是守护进程
特点:

  1. 随系统启动而启动
  2. 父进程是init,也就是ppid为1
  3. 在后台运行
  4. 进程名字通常以字母 d 结束
  5. ps显示中终端名设置为问号(?),终端前台进程组ID设置为-1
  6. 工作目录为 \ (根)

创建守护进程

  • 让程序在后台执行:调用fork()产生一个子进程,然后使父进程退出
  • 调用setsid()创建一个新对话期。控制终端、登录会话和进程组通常是从父进程进程下来的,守护进程要摆脱他们,不受他们的影响,方法是调用setsid()使进程成为一个会话组长。
  • 禁止进程重新申请打开控制终端。通过使进程不再是会话组长来实现。再一次通过fork创建新的子进程,使调用fork的进程退出。
  • 关闭不再需要的文件描述符。首先获得最高文件描述符值,然后用一个循环程序,关闭0到最高文件描述符值的所有文件描述符。
  • 将当前目录更改为根目录
  • 子进程从父进程继承的文件创建屏蔽字可能会拒绝某些许可权。为防止这一点,使用unmask(0)将屏蔽字清零。
  • 将SIGCHLD信号的操作设置为SIG_IGN,子进程结束的时候就不会产生僵尸进程。

守护进程与后台进程

后台进程的文件描述符是继承于父进程,例如shell,所以它也可以在当前终端下显示输出数据。
但是deemon进程自己变成了进程组长,其文件描述符号和控制终端没有关联,是控制台无关的。
基本上任何一个程序都可以后台运行,但守护进程是具有特殊要求的程序,比如要脱离自己的父进程,成为自己的会话组长等,这些要在代码中显式地写出来
所以守护进程是后台进程的一种
前台任务会随着session的退出而退出是因为它收到了SIGHUP信号。
后台任务是否会受到SIGNUP信号,取决于shell的 huponexit 参数。可以通过 $ shopt | grep huponexit 查看该参数的值。

Session

一般讨论的都是shell session,我们打开一个新的终端就会创建一个session
每个session都是由一个或者多个进程组组成的,每个进程组称为 job,这里job不是任务,而叫作业。
调用 setsid() 函数可以生成新的session,那么这些命令可以通过session进行统一管理
session中的第一个进程 (一般是bash) 的PID就是session的SID


评论
  目录