浅学进程的组成

74 阅读4分钟

进程:程序动态执行的过程, 在执行、运行的过程中,需要一定的资源比如:运行内存、CPU时间、磁盘、网络等

进程不等于程序,进程是程序动态执行的过程,而程序则是静态的存储在磁盘中的。 image.png

1.进程的组成a

image.png

2.进程的组成b

每个进程在运行时都有一个自己的 “CPU上下文”(硬件上下文)

eip : 32位操作系统,cpu中的寄存器, 存储cpu下一条要执行的指令

rip : 64位操作系统,cpu中的寄存器, 存储cpu下一条要执行的指令

进程中,肯定要知道下一条需要执行“ 指令 ”的内存地址,这个内存地址存储在cpu的 “程序计数器” 中

image.png image.png

image.png

小总结: image.png

3.进程的组成c

站在进程的角度, 每个进程都觉得自己有一颗CPU,真是没谁了~~ image.png 时分共享技术的实现,通过“时钟中断(异常号=32)”来实现 image.png 进程的组成大总结: 在Linux操作系统内核中,把每个进程都抽象成一个task_struct的结构体它包含了上面描述的那些变量 image.png task_struct结构体中的变量属性:

//标志信息
pid_t pid;                  // 进程ID
pid_t tgid;                 // 线程组ID(进程的主线程ID)
struct task_struct *group_leader;  // 线程组的领头线程

//亲缘关系———维护"进程之间的关系",是父子,还是兄弟
struct task_struct __rcu *real_parent;  // 真实父进程(创建该进程的原始父进程)
struct task_struct __rcu *parent;       // 当前父进程(接收SIGCHLD信号的进程)
struct list_head children;              // 子进程链表头
struct list_head sibling;               // 兄弟进程链表节点

//进程状态信息
volatile long state;        // 进程当前状态
int exit_state;             // 进程退出状态(退出时的具体状态)
unsigned int flags;         // 进程标志位

//文件 & 文件系统 信息
struct fs_struct *fs;       // 文件系统信息(当前目录、根目录等。fs包含的目录信息)
struct files_struct *files; // 打开文件表(files管理打开的文件描述符)

//内存管理 信息
struct mm_struct *mm;       // 进程内存管理描述符(mm管理进程的虚拟内存空间)

//内核栈 信息
struct thread_info  thread_info;  // 线程相关信息
void *stack;               // 内核栈指针

//信号处理 相关信息
struct signal_struct *signal;      // 进程共享信号处理结构
struct sighand_struct *sighand;    // 信号处理函数表
sigset_t blocked;          // 被阻塞的信号集
sigset_t real_blocked;     // 临时阻塞信号集(用于rt_sigtimedwait)
sigset_t saved_sigmask;    // 保存的信号掩码(用于TASK_RUNNING状态切换)
struct sigpending pending; // 待处理信号队列
unsigned long sas_ss_sp;   // 信号处理备用栈指针
size_t sas_ss_size;        // 信号处理备用栈大小
unsigned int sas_ss_flags; // 信号处理栈标志

//进程权限信息
const struct cred __rcu *read_cred;  // 读取权限凭证
const struct cred __rcu *cred;       // 当前有效权限凭证

//运行统计信息
u64 utime;                 // 用户态消耗的CPU时间
u64 stime;                 // 内核态消耗的CPU时间
unsigned long nvcsw;       // 自愿(voluntary)上下文切换计数
unsigned long nivcsw;      // 非自愿(involuntary)上下文切换计数
u64 start_time;            // 进程启动时间,不包含睡眠时间
u64 real_start_time;       // 进程启动时间,包含睡眠时间

//进程调度信息
int on_rq;                 // 是否在运行队列上(0-不在,1-在)
int prio;                  // 动态优先级
int static_prio;           // 静态优先级
int normal_prio;           // 基于静态优先级和调度策略计算的标准优先级
unsigned int rt_priority;  // 实时进程优先级
const struct sched_class *sched_class;  // 调度器类
struct sched_entity se;    // 普通调度实体
struct sched_rt_entity rt; // 实时调度实体
struct sched_dl_entity dl; // 截止时间调度实体
unsigned int policy;       // 调度策略(SCHED_NORMAL, SCHED_FIFO, SCHED_RR等)
int nr_cpus_allowed;       // 进程可运行的CPU数量
cpumask_t cpus_allowed;    // 进程可运行的CPU掩码(cpus_allowed限制进程只能在特定CPU上运行)
struct sched_info sched_info;  // 调度统计信息

进程与进程之间的小关系: image.png

4. Linux操作系统中的 0号进程、1号进程、2号进程

0号进程(idle进程):它是内核进程,所有进程的祖先,由于历史原因也叫"swapper进程"

  1. 配置实时时钟
  2. 挂载根文件系统
  3. 创建init进程(1号进程)
  4. 创建kthreadd进程(2号进程)

image.png

内核进程普通进程
只运行在“内核态”既可以运行在“内核态”,也可以运行在“用户态”
只能使用大于PAGE_OFFSET的虚拟地址空间可以使用所有的虚拟地址空间(运行在内核态就用内核的虚拟地址空间、运行在用户态就用用户态虚拟地址空间)

image.png

image.png