Linux软件编程:进程管理

一、进程基本概念

1. 程序与进程

  • 程序:静态的,存储在硬盘上的指令和数据的集合。

  • 进程:程序的一次执行过程,是系统进行资源分配和调度的基本单位,具有创建、执行、调度和终止的生命周期。


二、进程相关命令

1. 进程查看

  • top:实时查看系统进程及资源占用情况。

  • ps -ef:查看系统所有进程的详细信息。

  • ps -aux:查看进程状态、CPU和内存使用情况。

  • ps -ef | grep 进程名:查找指定进程。

2. 进程控制

  • kill -9 PID:强制终止指定PID的进程。

  • killall -9 进程名:终止所有同名进程。

  • &:在后台运行程序,如 ./a.out &

  • jobs:查看当前终端的所有后台任务。

  • fg 编号:将后台任务调至前台执行。

  • nice -n 优先级 任务:以指定优先级运行进程。

  • renice -n 优先级 PID:修改运行中进程的优先级。


三、进程的创建与地址空间

1. 虚拟地址与物理地址

  • 虚拟地址:通过MMU映射后进程可访问的内存空间。

  • 物理地址:实际的RAM地址,用户无法直接访问,需通过虚拟地址映射。

2. 虚拟地址空间布局(0-4G)

  • 文本段 (.text):存放程序代码。

  • 数据段

    • .rodata:只读数据(如字符串常量)。

    • .data:已初始化的全局变量和静态变量。

    • .bss:未初始化的全局变量和静态变量(进程启动时清零)。

  • 栈区 (.stack):存放局部变量,默认8M,由高向低增长。

  • 堆区 (.heap):动态分配内存区域,由低向高增长。

  • 内核空间:用户无法直接访问。

3. 进程空间独立性

  • 每个进程拥有独立的虚拟地址空间,映射到不同的物理内存区域,确保进程间互不干扰。

四、进程调度算法

  1. 先来先服务 (FCFS)

  2. 短作业优先 (SJF)

  3. 高优先级调度

  4. 时间片轮转 (RR):每个进程分配一个时间片(通常5-10ms),宏观上并行,微观上串行。

  5. 多级队列反馈调度

  6. 负载均衡调度

  7. 抢占式调度


五、进程状态

  • 运行态 (R):正在CPU执行。

  • 就绪态 (R):已准备好,等待CPU调度。

  • 可唤醒等待态 (S):等待资源,可被唤醒。

  • 不可唤醒等待态 (D):等待资源,不可中断。

  • 停止态 (T):被用户暂停。

  • 僵尸态 (Z):进程已结束,资源未回收。

  • 结束态 (X):进程结束且资源已回收。


六、进程相关函数接口

1. fork() -- 创建子进程

c

复制代码
pid_t fork(void);
  • 子进程复制父进程的代码、数据、堆栈等空间。

  • 父进程返回子进程PID,子进程返回0,失败返回-1。

2. getpid() -- 获取当前进程PID

c

复制代码
pid_t getpid(void);

3. getppid() -- 获取父进程PID

c

复制代码
pid_t getppid(void);

七、编程练习与实践

练习1:创建子进程并打印PID

创建两个子进程,分别打印自己的PID和父进程PID,父进程打印自己的PID和两个子进程的PID。

复制代码
末尾的while(1)也可以不用,但要再父进程打印那里加上一个sleep(5)函数,这是为了防止父进程提前结束,使得子进程的getppid()函数返回值错误



#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    pid_t ret1 = 0;
    pid_t ret2 = 0;

    ret1 = fork();

    if(-1 == ret1)
    {
        perror("fail to fork");
        return -1;
    }

    if(0 == ret1)
    {
        printf("我是子进程1: pid : %d ppid: %d\n", getpid(), getppid());
    }
    else if(ret1 > 0)
    {       
        ret2 = fork();

        if(-1 == ret2)
        {
            perror("fail to fork");
            return -1;
        }

        if(0 == ret2)
        {
            printf("我是子进程2: pid : %d ppid: %d\n", getpid(), getppid());
        }

        else if(ret2 > 0)
        {
            printf("我是父进程: pid : %d childpid1: %d childpid2: %d\n", getpid(), ret1, ret2);
        }


    }
    
    while(1)
    {

    }

    return 0;
}

练习2:遍历目录查找媒体文件

遍历指定目录,打印所有以 .flv.avi.rmvb.rm 结尾的文件。

相关推荐
IMPYLH4 小时前
Linux 的 split 命令
linux·运维·python·bash·运维开发·unix
0xDevNull4 小时前
分布式事务实战指南:从理论到Seata落地
java·开发语言·后端
椰猫子4 小时前
Spring Framework(Bean)
java·前端·spring
道清茗4 小时前
【RH294知识点汇总】第 7 章 《 使用角色和 Ansible 内容集合简化 Playbook 》
java·前端·ansible
cyber_两只龙宝4 小时前
【Oracle】Oracle之使用DML语言管理表
linux·运维·服务器·数据库·云原生·oracle
南境十里·墨染春水4 小时前
linux学习进展 线程同步——条件变量
java·开发语言·学习
Johnstons4 小时前
网络诊断工具怎么选:从监控告警到抓包定位的完整方法论
服务器·网络·php·es·抓包分析·网络诊断工具选型与排障方法
惊鸿若梦一书生5 小时前
《Python 高阶教程》016|偏函数与柯里化:把复杂调用拆成更简单的组合
linux·网络·python
窥视未来5 小时前
MySQL 性能调优完全指南:从硬件到 SQL,一篇吃透
java·数据库
senijusene5 小时前
基于 Linux SPI 子系统的 ADXL345 加速度传感器驱动开发
linux·运维·驱动开发