进程管理

进程管理

关于进程,需要记住三个组成部分:

  • 程序文件(Program file) - 代码和数据

  • 进程映像(Process image) - 存储栈、当前定义的变量、数据、地址空间等更多信息;当需要运行时,操作系统知道如何使用这个映像重新创建进程

  • 进程(Process) - 内存中运行的程序

当进程开始运行时,它会从父进程继承用户ID(user-id)组ID(group-id)。这个信息控制进程的访问级别。你可以使用setuidsetgid来启用进程继承文件所有者权限。

进程属性

每个进程都有以下属性:

  • 唯一标识符,称为进程ID或pid

  • 指向生成它的父进程的链接

有一个特殊的根父进程称为init,它通常有pid 1。initppid是0(传统上意味着它没有父进程)。pid 0对应内核调度器,它不是用户进程。

systemd现在正在Linux上取代init,它解决了init的一些问题并且整体更稳定,更多内容请参见这里

进程生命周期

UNIX中进程工作有一个通用模式:

  1. 通过克隆现有父进程创建新的子进程 fork()

  2. 这个新的子进程调用exec()来替换子进程中运行的父进程,用子进程想要运行的进程

  3. 子进程调用exit()来终止自己;它只传递退出码;0表示成功,其他都是错误码

  4. 父进程需要调用wait()系统调用来获取这个退出码

这个周期为每个生成的进程重复。

这里有一些可能出错的情况:

  • 如果父进程不调用wait()怎么办?这会导致僵尸进程(zombie process)- 这是一个资源泄漏,因为操作系统在退出码被父进程消费之前无法清理进程

  • 如果父进程在子进程之前死亡怎么办?这会导致孤儿进程(orphan process);孤儿进程init进程(特殊的根父进程)收养,然后等待子进程完成

父进程如何从子进程获取额外信息?使用退出码是不可能的。但是,有其他方法可以进行进程间通信

进程状态

进程可以处于以下几种状态:

  • 运行(Running): 正在CPU上执行

  • 就绪(Ready): 等待CPU执行

  • 阻塞(Blocked): 等待某个事件(如I/O操作)

  • 僵尸(Zombie): 已终止但父进程尚未调用wait()

  • 孤儿(Orphan): 父进程已终止,被init进程收养

进程管理命令

# 查看当前进程
$ ps
$ ps aux      # 详细信息
$ ps -ef      # 完整格式

# 查看进程树
$ pstree

# 动态查看进程
$ top
$ htop        # 更友好的界面

# 终止进程
$ kill <pid>          # 正常终止
$ kill -9 <pid>       # 强制终止
$ killall <name>      # 按名称终止

# 后台运行进程
$ command &
$ nohup command &     # 忽略挂断信号

# 查看进程详细信息
$ /proc/<pid>/status
$ /proc/<pid>/cmdline

进程优先级

# 查看进程优先级
$ top

# 更改进程优先级
$ renice -n 10 -p <pid>    # 降低优先级
$ renice -n -5 -p <pid>    # 提高优先级

# 以特定优先级启动进程
$ nice -n 10 command        # 低优先级
$ nice -n -5 command       # 高优先级

参考资料

最后更新于